package com.ctshk.rpc.order.air.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyRateExchangeConstant;
import com.ctshk.common.dto.Result;
import com.ctshk.common.dto.payment.CallPayDTO;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.payment.PayCurrency;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.req.pay.NotifyConsumeReq;
import com.ctshk.common.sms.core.SmsUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.vo.OrderRefundDTO;
import com.ctshk.rpc.air.dto.*;
import com.ctshk.rpc.air.req.*;
import com.ctshk.rpc.air.service.*;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.air.add.SupplierOrderSystemAirAddReq;
import com.ctshk.rpc.booking.req.system.air.add.SupplierSystemOrderAirAddReq;
import com.ctshk.rpc.booking.req.system.air.add.SupplierSystemOrderAirFlightAddReq;
import com.ctshk.rpc.booking.req.system.air.add.SupplierSystemOrderAirTicketAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.req.bill.BillAddCollectionReq;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.req.bill.BillOperateRefundReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.order.air.dto.*;
import com.ctshk.rpc.order.air.entity.*;
import com.ctshk.rpc.order.air.manager.AirOrderManager;
import com.ctshk.rpc.order.air.mapper.*;
import com.ctshk.rpc.order.air.req.*;
import com.ctshk.rpc.order.air.req.orderDetail.*;
import com.ctshk.rpc.order.air.service.IAirOrderReceiptService;
import com.ctshk.rpc.order.air.service.IAirOrderService;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.MainDataManualSystemDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.service.*;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ctshk.rpc.order.air.constants.OrderConstants.*;


/**
 * <p>
 * 机票订单 服务实现类
 * </p>
 *
 * @author lihang
 * @since 2021-03-15
 */
@Slf4j
@DubboService
public class AirOrderServiceImpl extends ServiceImpl<AirOrderMapper, AirOrder> implements IAirOrderService {

    @Autowired
    private AirOrderTouristMapper airOrderTouristMapper;

    @Autowired
    private AirManualOrderMapper airManualOrderMapper;

    @Autowired
    private AirOrderCollectionMapper airOrderCollectionMapper;

    @Autowired
    private AirOrderRefundMapper airOrderRefundMapper;

    @Autowired
    private AirOrderMapper airOrderMapper;

    @Autowired
    private AirOrderInsuranceMapper airOrderInsuranceMapper;

    @Autowired
    private AirOrderFlightMapper airOrderFlightMapper;

    @Autowired
    private IAirOrderReceiptService iAirOrderReceiptService;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private ISysDepartmentService iSysDepartmentService;

    @DubboReference
    private IAirProductService iAirProductService;

    @DubboReference
    private IAirProductCostService iAirProductCostService;

    @DubboReference
    private IAirFlightService iAirFlightService;
    /**
     * 汇率服务
     */
    @DubboReference
    private IMainDataCurrencyService mainDataCurrencyService;

    @DubboReference
    private IAirProductSaleRecordService iAirProductSaleRecordService;

    @DubboReference
    private ISupplierOrderService supplierOrderService;
    @DubboReference
    private IAirProductReservationSettingsService iAirProductReservationSettingsService;
    @DubboReference
    private ICrmMemberService iCrmMemberService;
    @Autowired
    private MailTemplate mailTemplate;
    @DubboReference
    private IFinanceBillService iFinanceBillService;
    @DubboReference
    private ISysApprovalService iSysApprovalService;
    @DubboReference
    private IMainDataManualSystemService iMainDataManualSystemService;
    @DubboReference
    private IAirProductCostTouristService iAirProductCostTouristService;

    @Override
    @Transactional
    public Result addOrder(AirOrderAddReq req, TokenUser tokenUser) {
        System.out.println("机票新增订单请求参数:" + JSON.toJSONString(req));
        /** 测试无法调通 先固定写死 调通接口
         UserDTO user = iSysUserService.loadUserByParam(tokenUser.getId(), 1);
         SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryByUserId(tokenUser.getId());
         */
        UserDTO user = new UserDTO();
        user.setEmployeeNumber("te_001");
        SysDepartmentDTO sysDepartmentDTO = new SysDepartmentDTO();
        sysDepartmentDTO.setDeptCode("td_001");
        /**通过航班计算价格*/
        List<AirOrderAddFlightReq> airOrderFlightDataList = req.getAirOrderFlightDataList();
        /**查询所有的产品 和航班*/
        List<Long> productIds = Lists.newArrayList();
        List<Long> airFlightIds = Lists.newArrayList();
        for (AirOrderAddFlightReq airOrderFlightData : airOrderFlightDataList) {
            productIds.add(airOrderFlightData.getProductId());
            airFlightIds.add(airOrderFlightData.getFlightId());
        }
        Map<Long, AirProductDTO> airProductDTOHashMap = Maps.newHashMap();
        List<AirProductDTO> airProductDTOList = iAirProductService.queryProductList(productIds);
        if (airProductDTOList.size() != airOrderFlightDataList.size()) {
            return Result.failed(SystemError.AIR_ORDER_15009);
        }
        for (AirProductDTO airProductDTO : airProductDTOList) {
            airProductDTOHashMap.put(airProductDTO.getId(), airProductDTO);
        }
        Map<Long, AirFlightDataDto> airFlightDataDtoMap = Maps.newHashMap();
        List<AirFlightDataDto> airFlightDataDtoList = iAirFlightService.listByIds(airFlightIds);
        for (AirFlightDataDto airFlightDataDto : airFlightDataDtoList) {
            airFlightDataDtoMap.put(airFlightDataDto.getId(), airFlightDataDto);
        }
        LocalDateTime createTime = LocalDateTime.now();
        BigDecimal orderAmount = new BigDecimal(0);//订单总金额
        BigDecimal serviceAmount = new BigDecimal(0);//订单服务费
        List<AirOrderFlight> airOrderFlightList = Lists.newArrayList();
        //创建航班信息
        /**开始验证价格*/
        for (AirOrderAddFlightReq airOrderFlightData : airOrderFlightDataList) {
            List<AirOrderFlightPriceData> orderFlightPriceDataList = airOrderFlightData.getOrderFlightPriceDataList();
            List<Long> touristTypeList = Lists.newArrayList();
            //旅客类型对应的航班价格信息Map
            Map<Long, AirOrderFlightPriceData> airOrderFlightPriceDataMap = Maps.newHashMap();
            for (AirOrderFlightPriceData airOrderFlightPriceData : orderFlightPriceDataList) {
                Integer touristType = airOrderFlightPriceData.getTouristTypeId();
                touristTypeList.add(touristType.longValue());
                airOrderFlightPriceDataMap.put(touristType.longValue(), airOrderFlightPriceData);
            }
            /**查询价格信息*/
            AirProductCostQueryReq airProductCostQueryReq = new AirProductCostQueryReq();
            if (null == req.getSalesmanId()) {
                airProductCostQueryReq.setRelationId(tokenUser.getId());
            } else {
                airProductCostQueryReq.setRelationId(req.getSalesmanId());
            }
            airProductCostQueryReq.setStarDate(airOrderFlightData.getDate());
            airProductCostQueryReq.setEndDate(airOrderFlightData.getDate());
            airProductCostQueryReq.setTouristTypeIds(touristTypeList);
            productIds.clear();
            productIds.add(airOrderFlightData.getProductId());
            airProductCostQueryReq.setProductIds(productIds);
            List<AirProductPriceDTO> airProductPriceDTOList = iAirProductCostService.queryProductCost(airProductCostQueryReq);
            AirProductPriceDTO airProductPriceDTO = airProductPriceDTOList.get(0);
            /*if (airProductPriceDTO.isForbidTheSale()) {//如果被禁售了  返回错误信息
                return Result.failed(SystemError.AIR_ORDER_15010);
            }*/

            if (ObjectUtils.isNotEmpty(airProductPriceDTO.getForbidTheSale()) && airProductPriceDTO.getForbidTheSale()) {//如果被禁售了  返回错误信息
                return Result.failed(SystemError.AIR_ORDER_15010);
            }

            List<AirProductPriceTouristDTO> airProductPriceTouristDTOList = airProductPriceDTO.getAirProductPriceTouristDTOList();
            if (CollectionUtil.isEmpty(airProductPriceTouristDTOList)) {//没有旅客  返回错误信息
                return Result.failed(SystemError.AIR_ORDER_15010);
            }
            if (airOrderFlightPriceDataMap.size() != airProductPriceTouristDTOList.size()) {//查询到价格的旅客 数量不一致
                return Result.failed(SystemError.AIR_ORDER_15010);
            }
            /**旅客从数据库查询到的价格信息*/
            Map<Long, AirProductPriceTouristDTO> touristPriceMap = Maps.newHashMap();
            for (AirProductPriceTouristDTO airProductPriceTouristDTO : airProductPriceTouristDTOList) {
                touristPriceMap.put(airProductPriceTouristDTO.getAirTouristTypeId().longValue(), airProductPriceTouristDTO);
            }
            List<AirOrderFlightPriceDBData> airOrderFlightPriceDBDataList = Lists.newArrayList();//存入数据的航班价格数据 保留有底价和服务费
            for (Map.Entry<Long, AirOrderFlightPriceData> entry : airOrderFlightPriceDataMap.entrySet()) {
                Long touristType = entry.getKey();
                //判断是否每个旅客都查询到了价格
                if (!touristPriceMap.containsKey(touristType)) {
                    return Result.failed(SystemError.AIR_ORDER_15010);
                }
                //判断日期是否一样
                AirProductPriceTouristDTO airProductPriceTouristDTO = touristPriceMap.get(touristType);
                AirProductPriceDateDTO airProductPriceDateDTO = airProductPriceTouristDTO.getAirProductPriceDateDTOList().get(0);
                if (!airProductPriceDateDTO.getDate().equals(airOrderFlightData.getDate())) {
                    return Result.failed(SystemError.AIR_ORDER_15010);
                }
                AirOrderFlightPriceData airOrderFlightPriceData = entry.getValue();
                BigDecimal price = airOrderFlightPriceData.getPrice();
                //如果价格不一样 则表示价格发生了变化
                if (airProductPriceDateDTO.getPrice().compareTo(price) != 0) {
                    return Result.failed(SystemError.AIR_ORDER_15010);
                }
                orderAmount = orderAmount.add(airProductPriceDateDTO.getPrice());
                //验证税费
                List<AirProductCostTaxationDTO> airProductCostTaxationDTOList = airProductPriceDateDTO.getAirProductCostTaxationDTOList();
                BigDecimal costTaxationPrice = new BigDecimal(0);
                for (AirProductCostTaxationDTO airProductCostTaxationDTO : airProductCostTaxationDTOList) {
                    costTaxationPrice = costTaxationPrice.add(airProductCostTaxationDTO.getAmount());
                }
                BigDecimal flightTaxationPrice = new BigDecimal(0);
                List<AirProductCostTaxationData> airProductCostTaxationDataList = airOrderFlightPriceData.getAirProductCostTaxationDTOList();
                for (AirProductCostTaxationData airProductCostTaxationData : airProductCostTaxationDataList) {
                    flightTaxationPrice = flightTaxationPrice.add(airProductCostTaxationData.getAmount());
                }
                if (flightTaxationPrice.compareTo(costTaxationPrice) != 0) {
                    return Result.failed(SystemError.AIR_ORDER_15010);
                }
                orderAmount = orderAmount.add(costTaxationPrice);
                serviceAmount = serviceAmount.add(airProductPriceDateDTO.getServiceChargePrice());
                //验证库存
                Integer dailyStock = airProductPriceDateDTO.getDailyStock();
                if (req.getAirOrderTouristDataList().size() > dailyStock.intValue()) {
                    return Result.failed(SystemError.AIR_ORDER_15009);
                }
                AirOrderFlightPriceDBData airOrderFlightPriceDBData = EntityUtil.copy(airOrderFlightPriceData, AirOrderFlightPriceDBData.class);
                airOrderFlightPriceDBData.setServiceChargePrice(airProductPriceDateDTO.getServiceChargePrice());
                airOrderFlightPriceDBData.setBasePrice(airProductPriceDateDTO.getBasePrice());
                airOrderFlightPriceDBDataList.add(airOrderFlightPriceDBData);
            }
            //组装航班价格信息
            AirFlightDataDto airFlightDataDto = airFlightDataDtoMap.get(airOrderFlightData.getFlightId());
            AirOrderFlight airOrderFlight = EntityUtil.copy(airFlightDataDto, AirOrderFlight.class);
            airOrderFlight.setFlightId(airFlightDataDto.getId());
            airOrderFlight.setProductId(airOrderFlightData.getProductId());
            AirProductDTO airProductDTO = airProductDTOHashMap.get(airOrderFlightData.getProductId());
            airOrderFlight.setDate(airOrderFlightData.getDate());
            airOrderFlight.setProductType(airProductDTO.getSource());
            airOrderFlight.setCabinClass(airProductDTO.getCabinClass());
            airOrderFlight.setCabinName(airProductDTO.getCabinName());
            airOrderFlight.setTimeConsuming(AirOrderManager.getTimeConsuming(airFlightDataDto.getDepTime(), airFlightDataDto.getArrTime()));
            airOrderFlight.setId(IdWorker.getId());
            airOrderFlight.setCreateId(tokenUser.getId());
            airOrderFlight.setGmtCreate(createTime);
            airOrderFlight.setModifiedId(tokenUser.getId());
            airOrderFlight.setGmtModified(createTime);
            airOrderFlight.setIsDeleted(IsDeletedCode.NO.getCode());
            airOrderFlight.setNumber(req.getAirOrderTouristDataList().size());
            airOrderFlight.setFlightPrice(JSON.toJSONString(airOrderFlightPriceDBDataList));
            airOrderFlightList.add(airOrderFlight);

        }
        /**验证会员 积分 和优惠码 如果使用了*/

        /**价格验证结束 开始组装订单信息*/
        Long airOrderId = IdWorker.getId();
        AirOrder airOrder = EntityUtil.copy(req, AirOrder.class);
        airOrder.setContactName(airOrder.getSurname() + airOrder.getName());
        airOrder.setId(airOrderId);
        airOrder.setCreateId(tokenUser.getId());
        airOrder.setGmtCreate(createTime);
        airOrder.setModifiedId(tokenUser.getId());
        airOrder.setGmtModified(createTime);
        airOrder.setIsDeleted(IsDeletedCode.NO.getCode());
        airOrder.setOrderAmount(orderAmount);
        airOrder.setServiceFee(serviceAmount);
        if (null == req.getSalesMethods()) {
            req.setSalesMethods(1);
        }
        airOrder.setSalesMethods(req.getSalesMethods());
        airOrder.setOrderNumber(AirOrderManager.getOrderNumer(sysDepartmentDTO.getDeptCode(), user.getEmployeeNumber()));
        airOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        airOrder.setCancelStatus(null);
        airOrder.setOrderStatus(OrderStatus.UN_PAYMENT.getCode());
        airOrder.setScheduledStatus(OrderScheduledStatus.CONFIRM_RESERVE.getCode());
        airOrder.setSource(OrderSource.CPM.getCode());

        if (null == airOrder.getSalesmanId()) {//如果没传销售人员 默认为当前登录用户
            airOrder.setSalesmanId(tokenUser.getId());
            airOrder.setSalesmanName(tokenUser.getUsername());
        }
        /**最晚付款时间为创建订单后15分钟*/
        airOrder.setPayExpireDate(createTime.plusMinutes(15));
        baseMapper.insert(airOrder);
        Map<String, Long> touristMap = Maps.newHashMap();
        for (AirOrderTouristData airOrderTouristData : req.getAirOrderTouristDataList()) {
            AirOrderTourist airOrderTourist = EntityUtil.copy(airOrderTouristData, AirOrderTourist.class);
            airOrderTourist.setId(IdWorker.getId());
            airOrderTourist.setOrderId(airOrderId);
            airOrderTourist.setCreateId(tokenUser.getId());
            airOrderTourist.setGmtCreate(createTime);
            airOrderTourist.setModifiedId(tokenUser.getId());
            airOrderTourist.setGmtModified(createTime);
            airOrderTourist.setIsDeleted(IsDeletedCode.NO.getCode());
            airOrderTourist.setTouristName(airOrderTourist.getSurname() + airOrderTourist.getName());
            airOrderTouristMapper.insert(airOrderTourist);
            touristMap.put(airOrderTouristData.getTouristFlag(), airOrderTourist.getId());
        }
        /**航班信息*/
        for (AirOrderFlight airOrderFlight : airOrderFlightList) {

            airOrderFlight.setId(IdWorker.getId());
            airOrderFlight.setOrderId(airOrderId);
            airOrderFlightMapper.insert(airOrderFlight);
            //锁库存(创建售卖记录)
            salesRecord(req.getAirOrderTouristDataList().size(), tokenUser,
                    airOrderFlight.getOrderId(), airOrderFlight.getProductId(), airOrderFlight.getDate());
        }

        /**保险信息*/
        if (NumberConstant.ONE.getValue().equals(req.getBuyInsurance())) {
            List<AirOrderInsuranceData> airOrderInsuranceReqList = req.getAirOrderInsuranceDataList();
            if (CollectionUtil.isEmpty(airOrderInsuranceReqList)) {
                new BusinessException(SystemError.AIR_ORDER_15005);
            }
            for (AirOrderInsuranceData airOrderInsuranceData : airOrderInsuranceReqList) {
                AirOrderInsurance airOrderInsurance = EntityUtil.copy(airOrderInsuranceData, AirOrderInsurance.class);
                airOrderInsurance.setId(IdWorker.getId());
                airOrderInsurance.setOrderId(airOrderId);
                airOrderInsurance.setCreateId(tokenUser.getId());
                airOrderInsurance.setGmtCreate(createTime);
                airOrderInsurance.setModifiedId(tokenUser.getId());
                airOrderInsurance.setGmtModified(createTime);
                airOrderInsurance.setIsDeleted(IsDeletedCode.NO.getCode());
                List<String> insuredPersons = airOrderInsuranceData.getTouristFlagList();
                StringBuffer insuredPersonBuf = new StringBuffer();
                for (String insuredPerson : insuredPersons) {
                    Long touristId = touristMap.get(insuredPerson);
                    if (null != touristId) {
                        new BusinessException(SystemError.AIR_ORDER_15006);
                    }
                    insuredPersonBuf.append("," + touristId.toString());
                }
                airOrderInsurance.setInsuredPerson(insuredPersonBuf.substring(1));
                airOrderInsuranceMapper.insert(airOrderInsurance);
            }
        }
        return Result.success(airOrderId);
    }

    /**
     * 创建售卖记录
     *
     * @param soldNumber
     * @param tokenUser
     * @param orderId
     * @param productId
     * @param date
     */
    private void salesRecord(int soldNumber, TokenUser tokenUser, Long orderId, Long productId, LocalDate date) {
        /**创建售卖记录*/
        AirProductSaleRecordAddReq airProductSaleRecordAddReq = new AirProductSaleRecordAddReq();
        airProductSaleRecordAddReq.setChannel(0);
        airProductSaleRecordAddReq.setCustomId(tokenUser.getId());
        airProductSaleRecordAddReq.setCustomName(tokenUser.getUsername());
        airProductSaleRecordAddReq.setOrderId(orderId);
        airProductSaleRecordAddReq.setProductId(productId);
        airProductSaleRecordAddReq.setSalesDate(date);
        airProductSaleRecordAddReq.setSoldNumber(soldNumber);
        iAirProductSaleRecordService.add(airProductSaleRecordAddReq, tokenUser.getId());
    }

    @Transactional
    @Override
    public Result addManualOrder(AirManualOrderAddReq req, TokenUser tokenUser) {
        /**订单总金额 = 支出金额 + 预订服务费 */
        UserDTO user = iSysUserService.loadUserByParam(tokenUser.getId(), 1);
        SysDepartmentDTO sysDepartmentDTO = iSysDepartmentService.queryByUserId(tokenUser.getId());
        if (Objects.isNull(user) || Objects.isNull(sysDepartmentDTO))
            return Result.failed(SystemError.USER_1002);
        //获取旅客数量
        if (CollectionUtil.isEmpty(req.getAirOrderTouristDataList()))
            throw new BusinessException(SystemError.AIR_ORDER_15012);
        Map<Integer, Long> touristNumber = req.getAirOrderTouristDataList()
                .parallelStream()
                .collect(Collectors.groupingBy(AirOrderTouristData::getTouristType, Collectors.counting()));
        //订单总额(汇率之后的)
        AtomicReference<BigDecimal> totalPriceAfterExchangeRate = new AtomicReference<BigDecimal>(BigDecimal.ZERO);
        //订单总额(汇率之前的)
        AtomicReference<BigDecimal> totalPriceBeforeExchangeRate = new AtomicReference<>(BigDecimal.ZERO);
        //取汇率
        MainDataCurrencyQueryDTO exchangeRate =
                getExchangeRateByCurrencyId(req.getCurrencyId());
        if (exchangeRate == null)
            throw new BusinessException(SystemError.AIR_ORDER_15011, req.getCurrencyName());
        //计算订单金额
        req.getAirManualOrderPriceReqList().stream().forEach(airManualOrderPriceReq -> {
            Long touristCount = touristNumber.get(airManualOrderPriceReq.getTouristTypeId());
            if (touristCount < 1)
                return;
            totalPriceAfterExchangeRate.set(totalPriceAfterExchangeRate.get().add(airManualOrderPriceReq
                    .getPrice()
                    //汇率转换
                    .multiply(exchangeRate.getPlannedExchangeRate())
                    //旅客数量
                    .multiply(BigDecimal.valueOf(touristCount))
                    .setScale(3, BigDecimal.ROUND_HALF_UP)
            ));

            totalPriceBeforeExchangeRate.set(totalPriceBeforeExchangeRate.get().add(
                    airManualOrderPriceReq.getPrice()
                            .multiply(BigDecimal.valueOf(touristCount))
                            .setScale(3, BigDecimal.ROUND_HALF_UP)
            ));
        });
        Long airManualOrderId = IdWorker.getId();//外挂单订单id
        Long airOrderId = IdWorker.getId(); //订单id
        AirManualOrder airManualOrder = EntityUtil.copy(req, AirManualOrder.class);
        airManualOrder.setOrderId(airManualOrderId);
        airManualOrder.setCreateId(tokenUser.getId());
        airManualOrder.setGmtCreate(LocalDateTime.now());
        airManualOrder.setModifiedId(tokenUser.getId());
        airManualOrder.setGmtModified(LocalDateTime.now());
        airManualOrder.setIsDeleted(IsDeletedCode.NO.getCode());
        airManualOrder.setOrderId(airOrderId);
        airManualOrder.setOrderAmount(totalPriceBeforeExchangeRate.get());
        airManualOrderMapper.insert(airManualOrder);
        /**组装订单信息*/
        AirOrder airOrder = new AirOrder();
        LocalDateTime createTime = LocalDateTime.now();
        airOrder.setId(airOrderId);
        airOrder.setTripType(req.getTripType());
        airOrder.setCreateId(tokenUser.getId());
        airOrder.setGmtCreate(createTime);
        airOrder.setModifiedId(tokenUser.getId());
        airOrder.setGmtModified(createTime);
        airOrder.setIsDeleted(IsDeletedCode.NO.getCode());
        airOrder.setPayExpireDate(LocalDateTime.now().plusMinutes(15));
        airOrder.setPaymentStatus(OrderPaymentStatus.UN_PAYMENT.getCode());
        airOrder.setCancelStatus(NumberConstant.ZERO.getValue());
        airOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
        airOrder.setSource(OrderSource.CPM.getCode());
        airOrder.setOrderType(1);
        /**订单联系人信息*/
        airOrder.setSurname(req.getSurname());
        airOrder.setName(req.getName());
        airOrder.setContactName(req.getContactName());
        airOrder.setContactMobile(req.getContactMobile());
        airOrder.setContactMobileAreaCodeId(req.getContactMobileAreaCodeId());
        airOrder.setContactMobileAreaCode(req.getContactMobileAreaCode());
        airOrder.setContactEmail(req.getContactEmail());
        airOrder.setAppellation(req.getAppellation());

        airOrder.setServiceFee(req.getServiceAmount());
        //订单金额+预订金=订单总额
        airOrder.setOrderAmount(totalPriceAfterExchangeRate.get().add(Optional.of(req.getServiceAmount()).orElse(BigDecimal.ZERO)));
        //订单状态
        airOrder.setOrderStatus(OrderStatus.UN_PAYMENT.getCode());
        //销售单号
        airOrder.setOrderNumber(AirOrderManager.getOrderNumer(sysDepartmentDTO.getDeptCode(), user.getEmployeeNumber()));
        baseMapper.insert(airOrder);
        /**  旅客信息 */
        List<AirOrderTourist> airOrderTouristList = EntityUtil.copyList(req.getAirOrderTouristDataList(), AirOrderTourist.class);
        for (AirOrderTourist airOrderTourist : airOrderTouristList) {
            airOrderTourist.setId(IdWorker.getId());
            airOrderTourist.setOrderId(airOrderId);
            airOrderTourist.setCreateId(tokenUser.getId());
            airOrderTourist.setGmtCreate(createTime);
            airOrderTourist.setModifiedId(tokenUser.getId());
            airOrderTourist.setGmtModified(createTime);
            airOrderTourist.setTouristName(airOrderTourist.getSurname() + airOrderTourist.getName());
            airOrderTourist.setIsDeleted(IsDeletedCode.NO.getCode());
            airOrderTouristMapper.insert(airOrderTourist);
        }
        /**航班信息*/
        List<AirManualOrderFlightReq> airManualOrderFlightReqList = req.getAirManualOrderFlightReqList();
        List<AirManualOrderPriceReq> airManualOrderPriceReqList = req.getAirManualOrderPriceReqList();
        for (AirManualOrderFlightReq airManualOrderFlightReq : airManualOrderFlightReqList) {
            List<AirOrderFlightPriceDBData> airOrderFlightPriceDBDataList = Lists.newArrayList();
            for (AirManualOrderPriceReq airManualOrderPriceReq : airManualOrderPriceReqList) {
                AirOrderFlightPriceDBData airOrderFlightPriceDBData = new AirOrderFlightPriceDBData();
                airOrderFlightPriceDBData.setServiceChargePrice(req.getServiceAmount());
                airOrderFlightPriceDBData.setCurrencyId(req.getCurrencyId());
                airOrderFlightPriceDBData.setCurrencyName(req.getCurrencyName());
                airOrderFlightPriceDBData.setPrice(airManualOrderPriceReq.getPrice());
                airOrderFlightPriceDBData.setTouristTypeId(airManualOrderPriceReq.getTouristTypeId());
                airOrderFlightPriceDBData.setTouristTypeName(airManualOrderPriceReq.getTouristTypeName());
                airOrderFlightPriceDBDataList.add(airOrderFlightPriceDBData);
            }
            AirOrderFlight airOrderFlight = EntityUtil.copy(airManualOrderFlightReq, AirOrderFlight.class);
            airOrderFlight.setFlightPrice(JSON.toJSONString(airOrderFlightPriceDBDataList));
            airOrderFlight.setOrderId(airOrderId);
            airOrderFlightMapper.insert(airOrderFlight);
        }
        return Result.success(airOrderId);
    }

    @Transactional
    @Override
    public Result payOrder(AirOrderPayReq req, TokenUser tokenUser) {
        AirOrder airOrder = baseMapper.selectById(req.getId());
        if (null == airOrder) {
            return Result.failed(SystemError.AIR_ORDER_15000);
        }
        //获取当前用户信息
        UserDTO user = iSysUserService.getUser(new UserDTO().setUsername(tokenUser.getUsername()));
        if (null == user) {
            return Result.failed(SystemError.USER_1002);
        }
        BigDecimal orderAmount = airOrder.getOrderAmount();
        List<AirOrderPayDetailReq> airOrderCollectionDetailReqList = req.getAirOrderCollectionDetailReqList();
/*        BigDecimal orderPayAmont = new BigDecimal(0);
        for (AirOrderPayDetailReq airOrderCollectionDetailReq : airOrderCollectionDetailReqList) {
            orderPayAmont.add(airOrderCollectionDetailReq.getCollectionAmount());
        }
        if (orderAmount.compareTo(orderPayAmont) != NumberConstant.ZERO.getValue().intValue()) {
            return Result.failed(SystemError.AIR_ORDER_15001);
        }*/
        if (req.getIsUnionpayDiscount().intValue() == NumberConstant.ONE.getValue().intValue() &&
                (null == req.getUnionpayDiscountId() || req.getUnionpayDiscountId().intValue() < NumberConstant.ONE.getValue().intValue())) {
            return Result.failed(SystemError.AIR_ORDER_15003);
        }
        BigDecimal marketExchangeRate = null;
        BigDecimal totalMoney = BigDecimal.ZERO;
        List<AirOrderCollection> airOrderCollectionList = Lists.newArrayList();
        for (AirOrderPayDetailReq airOrderCollectionDetailReq : airOrderCollectionDetailReqList) {
            AirOrderCollection airOrderCollection = EntityUtil.copy(airOrderCollectionDetailReq, AirOrderCollection.class);
            airOrderCollection.setCollectionNumber(AirOrderManager.getCollectionNumber());
            airOrderCollection.setIsPos(req.getIsPos());
            airOrderCollection.setIsUnionpayDiscount(req.getIsUnionpayDiscount());
            airOrderCollection.setUnionpayDiscountId(req.getUnionpayDiscountId());
            airOrderCollection.setId(IdWorker.getId());
            airOrderCollection.setOrderId(airOrder.getId());
            airOrderCollection.setCreateId(tokenUser.getId());
            airOrderCollection.setGmtCreate(LocalDateTime.now());
            airOrderCollection.setModifiedId(tokenUser.getId());
            airOrderCollection.setGmtModified(LocalDateTime.now());
            airOrderCollection.setIsDeleted(IsDeletedCode.NO.getCode());
            airOrderCollection.setSalerId(tokenUser.getId());
            airOrderCollection.setSalerName(tokenUser.getUsername());
            /******************************记录汇率 start*******************************/
            //获取汇率
            MainDataCurrencyQueryDTO exchangeRate =
                    getExchangeRateByCurrencyId(airOrderCollectionDetailReq.getCurrencyId());
            //保证汇率存在
            if (exchangeRate == null || exchangeRate.getMarketExchangeRate() == null) {
                throw new BusinessException(SystemError.AIR_ORDER_15011,
                        airOrderCollectionDetailReq.getCurrency());
            }
            marketExchangeRate = exchangeRate.getMarketExchangeRate();
            //当前汇率
            airOrderCollection.setExchangeRate(marketExchangeRate);
            BigDecimal divide = airOrderCollectionDetailReq.getCollectionAmount().multiply(marketExchangeRate).setScale(3, BigDecimal.ROUND_DOWN);
            //计算金额
            airOrderCollection.setExchangeRateAfterMoney(
                    divide
            );
            //汇率ID
            airOrderCollection.setExchangeRateId(exchangeRate.getId());
            //累计金额
            totalMoney = totalMoney.add(divide);
            /*****************************记录汇率 end********************************/
            airOrderCollectionMapper.insert(airOrderCollection);
            airOrderCollectionList.add(airOrderCollection);
        }
        /****************************************供应商预订单 start********************************************************/
        //订单详情的金额需要<=实付金额
        if (airOrder.getOrderAmount().compareTo(totalMoney) > 0) {
            throw new BusinessException(SystemError.AIR_ORDER_15001);
        }
        //获取航班信息
        List<AirOrderFlight> airOrderFlightList = airOrderFlightMapper.selectList(
                Wrappers.<AirOrderFlight>lambdaQuery()
                        .eq(AirOrderFlight::getOrderId, airOrder.getId())
                        .groupBy(AirOrderFlight::getProductId));
        initiateSupplierOrder(tokenUser, airOrder, airOrderFlightList);
        /****************************************供应商预订单 end********************************************************/
        /****************************************是否立即确认 start********************************************************************/
        AtomicBoolean instantConfirmation = new AtomicBoolean(true);
        airOrderFlightList.stream().forEach(flight -> {
            AirProductReservationSettingsDTO data = iAirProductReservationSettingsService.getByProductId(flight.getProductId()).getData();
            if (Objects.isNull(data) || NumberConstant.ONE.getValue().equals(data.getIsConfirm())) {
                instantConfirmation.set(false);
            }
        });
        /****************************************是否立即确认 end********************************************************************/
        /**修改订单状态为已支付*/
        UpdateWrapper<AirOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(AirOrder::getId, airOrder.getId());
        updateWrapper.lambda().set(AirOrder::getModifiedId, tokenUser.getId());
        updateWrapper.lambda().set(AirOrder::getGmtModified, LocalDateTime.now());
        updateWrapper.lambda().set(AirOrder::getOrderStatus,
                instantConfirmation.get() ? OrderStatus.RESERVE_SUCCESS.getCode() : OrderStatus.CONFIRM_RESERVE.getCode());
        updateWrapper.lambda().set(AirOrder::getScheduledStatus,
                instantConfirmation.get() ? OrderScheduledStatus.RESERVE_SUCCESS.getCode() : OrderScheduledStatus.CONFIRM_RESERVE.getCode());
        updateWrapper.lambda().set(AirOrder::getPaymentStatus, OrderPaymentStatus.ALREADY_PAYMENT.getCode());
        baseMapper.update(null, updateWrapper);
        /**创建一条收款记录*/
        iAirOrderReceiptService.add(airOrder.getId(), tokenUser);
        /***********************************通知财务 start**********************************/
        List<BillAddCollectionReq> billAddCollectionList = Lists.newArrayList();
        //存放产品id列表
        List<Long> productIds = Lists.newArrayList();
        //产品编号列表
        List<String> productNumbers = Lists.newArrayList();
        //资源信息列表
        List<String> resourceInfoList = Lists.newArrayList();
        airOrderFlightList.parallelStream().forEach(airOrderFlight -> {
            productIds.add(airOrderFlight.getProductId());
            resourceInfoList.add(airOrderFlight.getDepCityName() + "-" + airOrderFlight.getArrCityName());
            AirProductInfoDTO data = iAirProductService.info(airOrderFlight.getProductId()).getData();
            if (!Objects.isNull(data)) {
                productNumbers.add(data.getCode());
            }
        });
        //获取航班信息
        airOrderCollectionList.stream().forEach(airOrderCollection -> {
            BillAddCollectionReq billAddCollectionReq = new BillAddCollectionReq();
            //        单号
            billAddCollectionReq.setBillNumber(airOrderCollection.getCollectionNumber());
            //        业务类型
            billAddCollectionReq.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            //        收款方式ID
            billAddCollectionReq.setCollectionWayId(airOrderCollection.getCollectionWayId());
            //        收款方式
            billAddCollectionReq.setCollectionWayName(airOrderCollection.getCollectionWay());
            //        收款类型ID
            billAddCollectionReq.setCollectionTypeId(CollectionTypeIdCode.FULL.getCode());
            //        收款类型
            billAddCollectionReq.setCollectionTypeName(CollectionTypeIdCode.FULL.getMsg());
            //        收款金额
            billAddCollectionReq.setCollectionAmount(airOrderCollection.getCollectionAmount());
            //        币种ID
            billAddCollectionReq.setCurrencyId(airOrderCollection.getCurrencyId());
            //        币种名称
            billAddCollectionReq.setCurrencyName(airOrderCollection.getCurrency());
            //        汇率
            billAddCollectionReq.setExchangeRate(airOrderCollection.getExchangeRate().doubleValue());
            //        收款时间
            billAddCollectionReq.setCollectionTime(LocalDateTime.now());
            //        收款凭证JSON
            try { //避免出行json格式不对导致异常
                if (StringUtils.isNotBlank(airOrderCollection.getCollectionCertificateJson())){
                    billAddCollectionReq.setCollectionVoucherJsonList(
                            JSONArray.parseArray(airOrderCollection.getCollectionCertificateJson(), FileJson.class)
                    );
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
            //        销售单号
            billAddCollectionReq.setSaleOrderNumber(airOrder.getOrderNumber());
            //        销售单ID
            billAddCollectionReq.setSaleOrderId(airOrder.getId());
            //        产品ID
            billAddCollectionReq.setProductId(productIds);
            //        产品编号/团号
//            billAddCollectionReq.setProductNumber(productNumbers);
            //        产品名称
//            billAddCollectionReq.setProductName();
            //        资源信息
            billAddCollectionReq.setResourceInfo(resourceInfoList);
            //        销售人员ID
            billAddCollectionReq.setSaleUserId(tokenUser.getId());
            //        销售人员名称
            billAddCollectionReq.setSaleUserName(tokenUser.getNickname());
            //        销售部门ID
            billAddCollectionReq.setSaleDeptId(user.getDeptId());
            //        用户ID
            billAddCollectionReq.setUserId(tokenUser.getId());
            billAddCollectionList.add(billAddCollectionReq);
        });
        Result result = iFinanceBillService.addCollection(billAddCollectionList);
        if (result.getCode() != 0)
            throw new BusinessException(SystemError.AIR_ORDER_15015, result.getMsg());
        else
            airOrderCollectionMapper.update(new AirOrderCollection().setStatus(
                    OrderConfirmationStatus.UNRECOGNIZED.getStatus()),
                    Wrappers.<AirOrderCollection>lambdaUpdate().eq(AirOrderCollection::getOrderId, airOrder.getId()));
        /***********************************通知财务 end**********************************/
        return Result.success(airOrder.getId());
    }

    @Override
    public Result payment(NotifyConsumeReq notifyConsumeReq) throws Exception {
        return null;
    }

    /**
     * 发起供应商订单
     *
     * @param tokenUser
     * @param airOrder
     * @param airOrderFlightList
     * @return 是否立即确认
     */
    private boolean initiateSupplierOrder2(TokenUser tokenUser, AirOrder airOrder, List<AirOrderFlight> airOrderFlightList) {
        if (CollectionUtil.isEmpty(airOrderFlightList)) return false;
        //获取航班信息
        //获取当前用户信息
        UserDTO user = iSysUserService.getUser(new UserDTO().setUsername(tokenUser.getUsername()));
        if (user == null)
            throw new BusinessException(SystemError.USER_1002);
        //如果有需要二次预订的 这个值则会变成false
        AtomicBoolean scheduledFlag = new AtomicBoolean(true);
        //查询旅客信息
        List<AirOrderTourist> airOrderTouristList = airOrderTouristMapper.selectList(Wrappers.
                <AirOrderTourist>lambdaQuery()
                .eq(AirOrderTourist::getOrderId, airOrder.getId()));
        airOrderFlightList.stream().forEach(airOrderFlight -> {
            AirProductInfoDTO product = iAirProductService.info(airOrderFlight.getProductId()).getData();
            //发起供应商预订单参数对象
            SupplierOrderSystemAirAddReq supplierOrderSystemAirAddReq = new SupplierOrderSystemAirAddReq();
            Integer productSource = null;
            if (product != null) {
                productSource = product.getSource();
                //查询机票产品预订设置
                AirProductReservationSettingsDTO airProductReservationSettings =
                        iAirProductReservationSettingsService.getByProductId(product.getId()).getData();
                Assert.notNull(airProductReservationSettings, "机票产品预订设置不存在");
                //是否二次确认
                Integer isConfirm = airProductReservationSettings.getIsConfirm();
                //0-否
                if (isConfirm == null || isConfirm == 1) {
                    scheduledFlag.set(false);
                }
                //供应商ID
                supplierOrderSystemAirAddReq.setSupplierId(product.getSupplierId());
                //供应商名称
                supplierOrderSystemAirAddReq.setSupplierName(product.getSupplierName());
                //产品编号(通用)
                supplierOrderSystemAirAddReq.setProductNumber(product.getCode());
                //产品名称(通用)
                AirFlightDataDto data = iAirFlightService.query(new AirFlightQueryReq(product.getRouteId())).getData();
                if (data != null) {
                    supplierOrderSystemAirAddReq.setProductName(data.getDepCityName() + "-" + data.getArrAirportName());
                }
            }
            //订单类型
            supplierOrderSystemAirAddReq.setOrderType(1);

            //供应商订单类型(1:普通订单,2:内部挂账订单)
            supplierOrderSystemAirAddReq.setSupplierOrderType("1");
            //供应商销售编号/部门ID(根据'供应商订单编号'显示，1：供应商销售编号，2：部门ID)
//                supplierOrderSystemAirAddReq.setOriginalSaleNumber();
            supplierOrderSystemAirAddReq.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            supplierOrderSystemAirAddReq.setReserveTypeId(SupplierReserveTypeEnum.AIR.getId());
            //产品类型
            if (Integer.valueOf(1).equals(airOrder.getOrderType())) {
                supplierOrderSystemAirAddReq.setProductType(ProductType.PLUG.getCode());
                //外挂单出票类型
                AirManualOrder airManualOrder = airManualOrderMapper.selectOne(Wrappers
                        .<AirManualOrder>lambdaQuery()
                        .eq(AirManualOrder::getOrderId, airOrder.getId()));
                supplierOrderSystemAirAddReq.setTicketMode(airManualOrder != null ? airManualOrder.getIssueTicket() : null);
                //外挂单的供应商
                MainDataManualSystemDTO mainDataManualSystemDTO =
                        iMainDataManualSystemService.findById(airManualOrder.getSystemId()).getData();
                if (mainDataManualSystemDTO != null) {
                    //供应商ID
                    supplierOrderSystemAirAddReq.setSupplierId(mainDataManualSystemDTO.getSupplierId());
                    //供应商名称
                    supplierOrderSystemAirAddReq.setSupplierName(mainDataManualSystemDTO.getSupplierName());
                }
            } else {
                supplierOrderSystemAirAddReq.setProductType(
                        Integer.valueOf(2).equals(productSource) ?
                                ProductType.API_PRODUCT.getCode() :
                                ProductType.MANUAL_ENTRY.getCode()
                );
            }
            //资源所属部门ID(当前用户部门ID)
            supplierOrderSystemAirAddReq.setDepartmentId(user.getDeptId());
            //资源所属部门
            supplierOrderSystemAirAddReq.setDepartment(user.getDept());
            //销售单号(通用)
            supplierOrderSystemAirAddReq.setSaleNumber(airOrder.getOrderNumber());
            //总金额
            supplierOrderSystemAirAddReq.setTotalFee(airOrder.getOrderAmount());
            MainDataCurrencyQueryDTO currencyEntity = mainDataCurrencyService.getExchangeCurrencyEntity("HKD", CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
            supplierOrderSystemAirAddReq.setCurrencyId(currencyEntity.getId());
            supplierOrderSystemAirAddReq.setCurrency(currencyEntity.getCurrencyName());
            //应付金额
            supplierOrderSystemAirAddReq.setPayableAmount(airOrder.getReceivableAmount());
            //TODO 付款类型ID,当值'内部挂账'时'scheduleId'不能为空,,枚举PayRefundMethod
//                supplierOrderSystemAirAddReq.setPayTypeId();
            //付款类型
//                supplierOrderSystemAirAddReq.setPayType();
            //附件文件JSON
            supplierOrderSystemAirAddReq.setFilesJson(airOrder.getOrderDetails());
            List<AirOrderFlight> airOrderFlights = airOrderFlightMapper.selectList(
                    Wrappers.<AirOrderFlight>lambdaQuery()
                            .eq(AirOrderFlight::getOrderId, airOrderFlight.getOrderId())
                            .eq(AirOrderFlight::getProductId, airOrderFlight.getProductId()));
            List<SupplierSystemOrderAirAddReq> supplierSystemOrderAirAddReqList = airOrderFlights.parallelStream().map(airOrderFlight1 -> {
                SupplierSystemOrderAirAddReq supplierSystemOrderAirAddReq = new SupplierSystemOrderAirAddReq();
                supplierSystemOrderAirAddReq.setOrderId(airOrderFlight1.getOrderId());
                supplierSystemOrderAirAddReq.setAirportCompanyId(airOrderFlight1.getCompanyId());
                supplierSystemOrderAirAddReq.setAirportCompany(airOrderFlight1.getCompanyName());
                //出发地json格式
                JSONObject goLocationJson = new JSONObject();
                goLocationJson.put("Departure", airOrderFlight1.getDepCityName());
                goLocationJson.put("DepartureAirport", airOrderFlight1.getDepAirportName());
                supplierSystemOrderAirAddReq.setGoLocationJson(goLocationJson.toJSONString());
                //目的地json
                JSONObject desLocationJson = new JSONObject();
                desLocationJson.put("Destination", airOrderFlight1.getArrCityName());
                desLocationJson.put("DestinationAirport", airOrderFlight1.getArrAirportName());
                supplierSystemOrderAirAddReq.setDesLocationJson(desLocationJson.toJSONString());
                try {
                    AirOrderFlightPriceData airOrderFlightPriceData = JSON.parseObject(airOrderFlight1.getFlightPrice(), AirOrderFlightPriceData.class);
                    supplierSystemOrderAirAddReq.setCurrency(airOrderFlightPriceData.getCurrencyName());
                    supplierSystemOrderAirAddReq.setCurrencyId(airOrderFlightPriceData.getCurrencyId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                supplierSystemOrderAirAddReq.setSupplierSystemOrderAirTicketAddReqList(
                        airOrderTouristList.parallelStream().map(airOrderTourist -> {
                            SupplierSystemOrderAirTicketAddReq supplierSystemOrderAirTicketAddReq =
                                    new SupplierSystemOrderAirTicketAddReq();
                            supplierSystemOrderAirTicketAddReq.setOrderId(airOrderTourist.getOrderId());
                            //旅客姓名
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristName(airOrderTourist.getTouristName());
                            //国籍
                            supplierSystemOrderAirTicketAddReq.setNation(airOrderTourist.getNationalityName());
                            //旅客类型ID
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristTypeId(Long.valueOf(airOrderTourist.getTouristType()));
                            //旅客类型
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristType(String.valueOf(airOrderTourist.getTouristType()));
                            //证件类型ID
                            supplierSystemOrderAirTicketAddReq.setCertificateTypeId(airOrderTourist.getCertificatesTypeId());
                            //证件类型
                            supplierSystemOrderAirTicketAddReq.setCertificateType(airOrderTourist.getCertificatesType());
                            //证件号
                            supplierSystemOrderAirTicketAddReq.setCertificateNumber(
                                    airOrderTourist.getCertificatesNumber());
                            SupplierSystemOrderAirFlightAddReq supplierSystemOrderAirFlightAddReq =
                                    new SupplierSystemOrderAirFlightAddReq();
                            supplierSystemOrderAirFlightAddReq.setOrderId(airOrder.getId());
                            supplierSystemOrderAirFlightAddReq.setGoLocationJson(goLocationJson.toJSONString());
                            supplierSystemOrderAirFlightAddReq.setDesLocationJson(desLocationJson.toJSONString());
                            supplierSystemOrderAirFlightAddReq.setFlightNumber(airOrderFlight1.getFlightNumber());
//                            supplierSystemOrderAirTicketAddReq.setSupplierSystemOrderAirFlightAddReq(supplierSystemOrderAirFlightAddReq);
                            return supplierSystemOrderAirTicketAddReq;
                        }).collect(Collectors.toList())
                );
                return supplierSystemOrderAirAddReq;
            }).collect(Collectors.toList());
            supplierOrderSystemAirAddReq.setSupplierSystemOrderAirAddReqList(supplierSystemOrderAirAddReqList);
            Result<Long> result = supplierOrderService.addSystemAir(supplierOrderSystemAirAddReq, tokenUser.getId());
            Assert.isTrue(result.getCode() == 0,
                    String.format("发起供应商预订单失败,失败原因:[%s]", result.getMsg()));
        });
        //如果没有需要二次确认的 则修改成確認預訂
/*        if (scheduledFlag.get()) {
            airOrder.setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode());
            airOrder.setOrderStatus(OrderStatus.RESERVE_SUCCESS.getCode());
        }*/
        return scheduledFlag.get();
    }

    /**
     * 供应商预订单
     * 根据供应商分组 有几个供应商就下多少个单
     *
     * @param tokenUser
     * @param airOrder
     * @param airOrderFlightList
     */
    private void initiateSupplierOrder(TokenUser tokenUser, AirOrder airOrder, List<AirOrderFlight> airOrderFlightList) {
        if (CollectionUtils.isEmpty(airOrderFlightList)) return;
        //外挂单
        if (NumberConstant.ONE.getValue().equals(airOrder.getOrderType())) {
            outsideOrderInitiateSupplierOrder(tokenUser, airOrder, airOrderFlightList);
            return;
        }
        //获取产品信息
        List<Long> productIds = airOrderFlightList.stream()
                .map(airOrderFlight -> airOrderFlight.getProductId()).collect(Collectors.toList());
        //查询产品列表
        AirProductListReq productListReq = new AirProductListReq();
        productListReq.setPageSize(productIds.size());
        productListReq.setProductIds(productIds);
        PageResponse<AirProductListDTO> data =
                iAirProductService.list(productListReq).getData();
        com.ctshk.common.utils.Assert.nonNull(data, SystemError.AIR_PRODUCT_12004);
        List<AirProductListDTO> productList = data.getRecords();
        //查询出来的产品需要和传入的数量一样
        com.ctshk.common.utils.Assert.isTrue(CollectionUtils.isNotEmpty(productList)
                && productIds.size() == productIds.size(), SystemError.AIR_ORDER_15026);
        //根据供应商id分组
        Map<Long, List<AirProductListDTO>> map =
                productList.stream().collect(Collectors.groupingBy(AirProductListDTO::getSupplierId));
        //获取航班id
        Set<Long> routeIds = productList.stream().map(AirProductListDTO::getRouteId).collect(Collectors.toSet());
        //获取航班信息
        List<AirFlightDataDto> flightList = iAirFlightService.listByIds(Lists.newArrayList(routeIds));
        //转map key=Id
        Map<Long, AirFlightDataDto> flightMap = flightList.stream()
                .collect(Collectors.toMap(AirFlightDataDto::getId, Function.identity()));
        //获取港币信息
        MainDataCurrencyQueryDTO hkdCurrency = mainDataCurrencyService.
                getExchangeCurrencyEntity("HKD", CurrencyRateExchangeConstant.MARKET_EXCHANGE_RATE_);
        //获取当前用户信息
        UserDTO user = iSysUserService.getUser(new UserDTO().setUsername(tokenUser.getUsername()));
        //获取旅客信息
        List<AirOrderTourist> touristList = airOrderTouristMapper
                .selectList(Wrappers.<AirOrderTourist>lambdaQuery().eq(AirOrderTourist::getOrderId, airOrder.getId()));
        map.forEach((k, v) -> {
            List<SupplierSystemOrderAirAddReq> supplierSystemOrderAirAddReqList = Lists.newArrayList();
            v.stream().forEach(product -> {
                AirProductCostDTO costDTO = iAirProductCostTouristService.selectByProductIdAndTouristTypes(product.getId(),
                        touristList.stream().map(AirOrderTourist::getTouristType).collect(Collectors.toList()));
                com.ctshk.common.utils.Assert.nonNull(costDTO, SystemError.AIR_PRODUCT_12025);
                com.ctshk.common.utils.Assert.notEmpty(costDTO.getAirProductCostTouristDTOList(), SystemError.AIR_PRODUCT_12025);
                List<AirProductCostTouristDTO> airProductCostTouristDTOList = costDTO.getAirProductCostTouristDTOList();
                AirFlightDataDto flightData = flightMap.get(product.getRouteId());
                SupplierSystemOrderAirAddReq supplierSystemOrderAirAddReq = new SupplierSystemOrderAirAddReq();
                supplierSystemOrderAirAddReq.setOrderId(airOrder.getId());
                supplierSystemOrderAirAddReq.setAirportCompanyId(flightData.getCompanyId());
                supplierSystemOrderAirAddReq.setAirportCompany(flightData.getCompanyName());
//                supplierSystemOrderAirAddReq.setOutSystemId();
//                supplierSystemOrderAirAddReq.setOutSystem();
                JSONObject goLocationJson = new JSONObject();
                //出发地Json
                goLocationJson.put("Departure", product.getDepCityName());
                goLocationJson.put("DepartureAirport", product.getDepAirportName());
                supplierSystemOrderAirAddReq.setGoLocationJson(goLocationJson.toJSONString());
                //目的地json
                JSONObject desLocationJson = new JSONObject();
                desLocationJson.put("Destination", product.getArrCityName());
                desLocationJson.put("DestinationAirport", product.getArrAirportName());
                supplierSystemOrderAirAddReq.setDesLocationJson(desLocationJson.toJSONString());
                supplierSystemOrderAirAddReq.setGoFlight(product.getFlightNumber());
                supplierSystemOrderAirAddReq.setCurrencyId(costDTO.getCurrencyId());
                supplierSystemOrderAirAddReq.setCurrency(costDTO.getCurrencyName());
                supplierSystemOrderAirAddReq.setSpendAmount(
                        airProductCostTouristDTOList.stream().map(AirProductCostTouristDTO::getCostPrice).reduce(BigDecimal.ZERO, BigDecimal::add)
                );
                supplierSystemOrderAirAddReq.setReservAmount(
                        airProductCostTouristDTOList.stream().map(AirProductCostTouristDTO::getTaxation).reduce(BigDecimal.ZERO, BigDecimal::add)
                );
                //根据旅客类型分组
                Map<Long, AirProductCostTouristDTO> touristMap = airProductCostTouristDTOList.stream()
                        .collect(Collectors.toMap(AirProductCostTouristDTO::getTouristTypeId, Function.identity()));
                supplierSystemOrderAirAddReq.setSupplierSystemOrderAirTicketAddReqList(
                        touristList.stream().map(airOrderTourist -> {
                            SupplierSystemOrderAirTicketAddReq supplierSystemOrderAirTicketAddReq =
                                    new SupplierSystemOrderAirTicketAddReq();
                            supplierSystemOrderAirTicketAddReq.setOrderId(airOrderTourist.getOrderId());
                            //旅客姓名
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristName(airOrderTourist.getTouristName());
                            //国籍
                            supplierSystemOrderAirTicketAddReq.setNation(airOrderTourist.getNationalityName());
                            //旅客类型ID
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristTypeId(Long.valueOf(airOrderTourist.getTouristType()));
                            //旅客类型
                            supplierSystemOrderAirTicketAddReq
                                    .setTouristType(String.valueOf(airOrderTourist.getTouristType()));
                            //证件类型ID
                            supplierSystemOrderAirTicketAddReq.setCertificateTypeId(airOrderTourist.getCertificatesTypeId());
                            //证件类型
                            supplierSystemOrderAirTicketAddReq.setCertificateType(airOrderTourist.getCertificatesType());
                            //证件号
                            supplierSystemOrderAirTicketAddReq.setCertificateNumber(
                                    airOrderTourist.getCertificatesNumber());
                            AirProductCostTouristDTO dto = touristMap.get(Long.valueOf(airOrderTourist.getTouristType()));
                            supplierSystemOrderAirTicketAddReq.setSinglePrice(dto.getCostPrice());
                            supplierSystemOrderAirTicketAddReq.setTaxAmount(dto.getTaxation());
                            supplierSystemOrderAirTicketAddReq.setTotalPrice(dto.getCostPrice().add(dto.getCostPrice()));
                            return supplierSystemOrderAirTicketAddReq;
                        }).collect(Collectors.toList())
                );
                supplierSystemOrderAirAddReqList.add(supplierSystemOrderAirAddReq);
            });
            SupplierOrderSystemAirAddReq req = new SupplierOrderSystemAirAddReq();
            AirProductListDTO airProduct = v.get(0);
            req.setOrderType(1);
//            req.setTicketMode();
            req.setSupplierId(airProduct.getSupplierId());
            req.setSupplierName(airProduct.getSupplierName());
            req.setSupplierOrderType("1");
            req.setOriginalSaleNumber(airOrder.getOrderNumber());
            req.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            req.setSaleType(SalesMethod.SINGLE_SALE.getCode());
            req.setReserveTypeId(SupplierReserveTypeEnum.AIR.getId());
            req.setProductType(ProductType.MANUAL_ENTRY.getCode());
            req.setDepartmentId(user.getDeptId());
            req.setDepartment(user.getDept());
            req.setSaleNumber(airOrder.getOrderNumber());
            String productNumbers = v.stream().map(AirProductListDTO::getCode).collect(Collectors.joining(","));
            String productNames = v.stream()
                    .map(product -> product.getDepAirportName() + "-" + product.getArrAirportName()).collect(Collectors.joining(","));
            req.setProductNumber(productNumbers);
            req.setProductName(productNames);
            req.setTotalFee(airOrder.getOrderAmount());
            req.setCurrencyId(hkdCurrency.getId());
            req.setCurrency(hkdCurrency.getCurrencyName());
            req.setPayableAmount(airOrder.getOrderAmount());
            req.setFilesJson(airOrder.getOrderDetails());
            req.setConfirmStatus(airOrder.getScheduledStatus());
            req.setRemark(airOrder.getRemark());
            req.setSupplierSystemOrderAirAddReqList(supplierSystemOrderAirAddReqList);
            supplierOrderService.addSystemAir(req, tokenUser.getId());
        });
    }

    /**
     * 外挂单发起供应商预订单
     *
     * @param tokenUser
     * @param airOrder
     * @param airOrderFlightList
     */
    private void outsideOrderInitiateSupplierOrder(TokenUser tokenUser, AirOrder airOrder, List<AirOrderFlight> airOrderFlightList) {
        //获取外挂单信息
        AirManualOrder airManualOrder = airManualOrderMapper.selectOne(Wrappers.
                <AirManualOrder>lambdaQuery().eq(AirManualOrder::getOrderId, airOrder.getId()));
        com.ctshk.common.utils.Assert.nonNull(airManualOrder, SystemError.AIR_ORDER_15016);
        //获取外挂系统数据
        //外挂单的供应商
        MainDataManualSystemDTO mainDataManualSystemDTO =
                iMainDataManualSystemService.findById(airManualOrder.getSystemId()).getData();
        com.ctshk.common.utils.Assert.nonNull(mainDataManualSystemDTO, SystemError.AIR_ORDER_15027);
        //获取当前用户信息
        UserDTO user = iSysUserService.getUser(new UserDTO().setUsername(tokenUser.getUsername()));
        com.ctshk.common.utils.Assert.nonNull(user, SystemError.USER_1002);
        SupplierOrderSystemAirAddReq req = new SupplierOrderSystemAirAddReq();
        req.setOrderType(1);
        req.setTicketMode(airManualOrder.getIssueTicket());
        req.setSupplierId(mainDataManualSystemDTO.getSupplierId());
        req.setSupplierName(mainDataManualSystemDTO.getSupplierName());
        req.setSupplierOrderType("1");
        req.setOriginalSaleNumber(airOrder.getOrderNumber());
        req.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
        req.setSaleType(SalesMethod.SINGLE_SALE.getCode());
        req.setReserveTypeId(SupplierReserveTypeEnum.AIR.getId());
        req.setProductType(ProductType.PLUG.getCode());
        req.setDepartmentId(user.getDeptId());
        req.setDepartment(user.getDept());
        req.setSaleNumber(airOrder.getOrderNumber());
        String productName = airOrderFlightList.stream()
                .map(flight -> flight.getDepAirportName() + "-" + flight.getArrAirportName()).collect(Collectors.joining(","));
        req.setProductName(productName);
        req.setTotalFee(airManualOrder.getOrderAmount());
        req.setCurrencyId(airManualOrder.getCurrencyId());
        req.setCurrency(airManualOrder.getCurrencyName());
        req.setPayableAmount(airManualOrder.getOrderAmount());
        req.setFilesJson(airOrder.getOrderDetails());
        req.setConfirmStatus(airOrder.getScheduledStatus());
        req.setRemark(airOrder.getRemark());
        //获取旅客信息
        List<AirOrderTourist> touristList = airOrderTouristMapper
                .selectList(Wrappers.<AirOrderTourist>lambdaQuery().eq(AirOrderTourist::getOrderId, airOrder.getId()));
        List<SupplierSystemOrderAirAddReq> supplierSystemOrderAirAddReqs = airOrderFlightList.stream().map(flight -> {
            SupplierSystemOrderAirAddReq airAddReq = new SupplierSystemOrderAirAddReq();
            airAddReq.setOrderId(airOrder.getId());
            airAddReq.setAirportCompanyId(flight.getCompanyId());
            airAddReq.setAirportCompany(flight.getCompanyName());
            airAddReq.setOutSystemId(mainDataManualSystemDTO.getId());
            airAddReq.setOutSystem(mainDataManualSystemDTO.getSystemName());
            //出发地json格式
            JSONObject goLocationJson = new JSONObject();
            goLocationJson.put("Departure", flight.getDepCityName());
            goLocationJson.put("DepartureAirport", flight.getDepAirportName());
            airAddReq.setGoLocationJson(goLocationJson.toJSONString());
            //目的地json
            JSONObject desLocationJson = new JSONObject();
            desLocationJson.put("Destination", flight.getArrCityName());
            desLocationJson.put("DestinationAirport", flight.getArrAirportName());
            airAddReq.setDesLocationJson(desLocationJson.toJSONString());
            airAddReq.setGoFlight(flight.getFlightNumber());
            airAddReq.setTicketType(airManualOrder.getTicketKind());
            airAddReq.setCurrencyId(airManualOrder.getCurrencyId());
            airAddReq.setCurrency(airManualOrder.getCurrencyName());
            airAddReq.setSpendAmount(airManualOrder.getOrderAmount());
            airAddReq.setReservAmount(airManualOrder.getServiceAmount());
            airAddReq.setPrintTicket(airManualOrder.getIssueTicket());
            airAddReq.setSupplierSystemOrderAirTicketAddReqList(
                    touristList.stream().map(airOrderTourist -> {
                        SupplierSystemOrderAirTicketAddReq supplierSystemOrderAirTicketAddReq =
                                new SupplierSystemOrderAirTicketAddReq();
                        supplierSystemOrderAirTicketAddReq.setOrderId(airOrderTourist.getOrderId());
                        //旅客姓名
                        supplierSystemOrderAirTicketAddReq
                                .setTouristName(airOrderTourist.getTouristName());
                        //国籍
                        supplierSystemOrderAirTicketAddReq.setNation(airOrderTourist.getNationalityName());
                        //旅客类型ID
                        supplierSystemOrderAirTicketAddReq
                                .setTouristTypeId(Long.valueOf(airOrderTourist.getTouristType()));
                        //旅客类型
                        supplierSystemOrderAirTicketAddReq
                                .setTouristType(String.valueOf(airOrderTourist.getTouristType()));
                        //证件类型ID
                        supplierSystemOrderAirTicketAddReq.setCertificateTypeId(airOrderTourist.getCertificatesTypeId());
                        //证件类型
                        supplierSystemOrderAirTicketAddReq.setCertificateType(airOrderTourist.getCertificatesType());
                        //证件号
                        supplierSystemOrderAirTicketAddReq.setCertificateNumber(
                                airOrderTourist.getCertificatesNumber());
                        String flightPrice = flight.getFlightPrice();
                        List<AirOrderFlightPriceData> flightPriceList = JSONArray.parseArray(flightPrice, AirOrderFlightPriceData.class);
                        com.ctshk.common.utils.Assert.notEmpty(flightPriceList, SystemError.AIR_ORDER_15028);
                        Map<Integer, AirOrderFlightPriceData> map = flightPriceList.stream()
                                .collect(Collectors.toMap(AirOrderFlightPriceData::getTouristTypeId, Function.identity()));
                        AirOrderFlightPriceData dto = map.get(airOrderTourist.getTouristType());
                        supplierSystemOrderAirTicketAddReq.setSinglePrice(dto.getPrice());
                        supplierSystemOrderAirTicketAddReq.setTaxAmount(BigDecimal.ZERO);
                        supplierSystemOrderAirTicketAddReq.setTotalPrice(
                                supplierSystemOrderAirTicketAddReq.getSinglePrice().add(supplierSystemOrderAirTicketAddReq.getTaxAmount())
                        );
                        return supplierSystemOrderAirTicketAddReq;
                    }).collect(Collectors.toList())
            );
            return airAddReq;
        }).collect(Collectors.toList());
        req.setSupplierSystemOrderAirAddReqList(supplierSystemOrderAirAddReqs);
        supplierOrderService.addSystemAir(req, tokenUser.getId());
    }

    /**
     * 根据订单id获取产品列表
     *
     * @param airOrder
     */
    private List<AirProductDTO> getProductByOrderId(AirOrder airOrder) {
        List<AirOrderFlight> airOrderFlightList = airOrderFlightMapper.selectList(
                Wrappers.<AirOrderFlight>lambdaQuery()
                        .eq(AirOrderFlight::getOrderId, airOrder.getId()));
        List<Long> productIdList = airOrderFlightList.stream()
                .map(airOrderFlight -> airOrderFlight.getProductId())
                .collect(Collectors.toList());
        List<AirProductDTO> airProductList = iAirProductService.queryProductList(productIdList);
        return airProductList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result refundOrder(AirOrderRefundReq req, TokenUser tokenUser) {
        AirOrder airOrder = baseMapper.selectById(req.getOrderId());
        if (null == airOrder) {
            return Result.failed(SystemError.AIR_ORDER_15000);
        }
        //不属于已付款时调用未付款取消订单接口
        if (airOrder.getPaymentStatus().intValue() != OrderPaymentStatus.ALREADY_PAYMENT.getCode().intValue()) {
            return cancelOrder(new AirOrderCancelReq(req.getOrderId(), req.getRejectReason(), req.getRemark()), tokenUser);
        }
        List<AirOrderRefundDetailReq> airOrderRefundDetailReqList = req.getAirOrderRefundDetailReqList();
        com.ctshk.common.utils.Assert.notEmpty(airOrderRefundDetailReqList, SystemError.AIR_ORDER_15025);
        BigDecimal refundAmount = BigDecimal.ZERO;
        for (AirOrderRefundDetailReq airOrderRefundDetailReq : airOrderRefundDetailReqList) {
            AirOrderRefund airOrderRefund = EntityUtil.copy(airOrderRefundDetailReq, AirOrderRefund.class);
            airOrderRefund.setId(IdWorker.getId());
            airOrderRefund.setOrderId(airOrder.getId());
            airOrderRefund.setCreateId(tokenUser.getId());
            airOrderRefund.setGmtCreate(LocalDateTime.now());
            airOrderRefund.setModifiedId(tokenUser.getId());
            airOrderRefund.setGmtModified(LocalDateTime.now());
            airOrderRefund.setIsDeleted(IsDeletedCode.NO.getCode());
            airOrderRefund.setRefundReason(req.getRejectReason());
            airOrderRefund.setOrderId(airOrder.getId());
            airOrderRefund.setStatus(OrderRefundStatus.AUDITING.getCode());
            airOrderRefund.setRefundNumber(AirOrderManager.getRefundNumber());
            /*********************记录汇率start*********************/
            //获取汇率
            MainDataCurrencyQueryDTO exchangeRate = getExchangeRateByCurrencyId(airOrderRefund.getCurrencyId());
            //保证汇率存在
            if (exchangeRate == null || exchangeRate.getMarketExchangeRate() == null) {
                throw new BusinessException(SystemError.AIR_ORDER_15011,
                        airOrderRefund.getCurrency());
            }
            BigDecimal marketExchangeRate = exchangeRate.getMarketExchangeRate();
            //当前汇率
            airOrderRefund.setExchangeRate(marketExchangeRate);
            //计算金额
            airOrderRefund.setExchangeRateAfterMoney(
                    airOrderRefund.getRefundAmount().divide(marketExchangeRate)
            );
            //汇率ID
            airOrderRefund.setExchangeRateId(exchangeRate.getId());
            /*********************记录汇率 end*********************/
            airOrderRefundMapper.insert(airOrderRefund);
            refundAmount = refundAmount.add(airOrderRefund.getExchangeRateAfterMoney());
        }
        //发起审批
        Result<ApprovalStartDTO> approveResult = iSysApprovalService.start(
                SystemBusinessType.AIR_TICKET.getCode(),
                SysApprovalType.CANCEL_AIR.getCode(),
                airOrder.getId(),
                tokenUser.getId(),
                refundAmount, null
        );
        if (!approveResult.isSuccess())
            throw new BusinessException(SystemError.getDefined(approveResult.getCode()));
        /**修改订单状态*/
        UpdateWrapper<AirOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(AirOrder::getId, airOrder.getId());
        updateWrapper.lambda().set(AirOrder::getModifiedId, tokenUser.getId());
        updateWrapper.lambda().set(AirOrder::getGmtModified, LocalDateTime.now());
        updateWrapper.lambda().set(AirOrder::getCancelStatus, OrderCancelStatus.UNDER_APPROVAL.getCode());
        updateWrapper.lambda().set(AirOrder::getRefundApprovalId, approveResult.getData().getApprovalId());
        baseMapper.update(null, updateWrapper);
        return Result.success(airOrder.getId());
    }

    @Transactional
    @Override
    public Result cancelOrder(AirOrderCancelReq req, TokenUser tokenUser) {
        AirOrder airOrder = airOrderMapper.selectById(req.getId());
        Long userId = tokenUser != null ? tokenUser.getId() : null;
        if (null == airOrder) {
            Result.failed(SystemError.AIR_ORDER_15000);
        }
        if (airOrder.getPaymentStatus().intValue() != OrderPaymentStatus.UN_PAYMENT.getCode().intValue()) {
            Result.failed(SystemError.AIR_ORDER_15007);
        }
        //修改订单装
        UpdateWrapper<AirOrder> airOrderUpdateWrapper = new UpdateWrapper<>();
        airOrderUpdateWrapper.lambda().eq(AirOrder::getId, req.getId());
        //修改付款状态为已取消
        airOrderUpdateWrapper.lambda().set(AirOrder::getPaymentStatus, OrderPaymentStatus.ALREADY_CANCEL.getCode());
        //修改预订状态为失败
        airOrderUpdateWrapper.lambda().set(AirOrder::getScheduledStatus, OrderScheduledStatus.RESERVE_FAIL.getCode());
        //修改取消状态为成功
        airOrderUpdateWrapper.lambda().set(AirOrder::getCancelStatus, OrderCancelStatus.ALREADY_REFUND.getCode());
        airOrderMapper.update(null, airOrderUpdateWrapper);
        //创建一条退款记录 记录退款原因
        AirOrderRefund airOrderRefund = new AirOrderRefund();
        airOrderRefund.setId(IdWorker.getId());
        airOrderRefund.setOrderId(airOrder.getId());
        airOrderRefund.setCreateId(userId);
        airOrderRefund.setGmtCreate(LocalDateTime.now());
        airOrderRefund.setModifiedId(userId);
        airOrderRefund.setGmtModified(LocalDateTime.now());
        airOrderRefund.setIsDeleted(IsDeletedCode.NO.getCode());
        airOrderRefund.setRefundReason(req.getRefundReason());
        airOrderRefund.setOrderId(airOrder.getId());
        if (StringUtils.isBlank(req.getRemark())) {
            airOrderRefund.setRemark("未付款取消订单");
        } else {
            airOrderRefund.setRemark(req.getRemark());
        }
        airOrderRefund.setStatus(OrderRefundStatus.REFUND_SUCCESSFUL.getCode());
        airOrderRefundMapper.insert(airOrderRefund);
        return Result.success(req.getId());
    }

    @Override
    public Result refundApproval(AirOrderRefundApprovalReq req, TokenUser tokenUser) {
        //通过审批id查找对应订单信息
        AirOrder order = airOrderMapper.selectOne(
                Wrappers.<AirOrder>lambdaQuery()
                        .eq(AirOrder::getRefundApprovalId, req.getApprovalId()));
        if (Objects.isNull(order))
            throw new BusinessException(SystemError.AIR_ORDER_15000);
        //校验审批状态是否正确
        ApprovalStatus approvalStatus = ApprovalStatus.getDefined(req.getStatus());
        if (Objects.isNull(approvalStatus))
            throw new BusinessException(SystemError.WORKFLOW_APPROVAL_7012);
        //调用审批系统接口
        Result<ApprovalCheckDTO> approvalResult = iSysApprovalService.check(
                req.getApprovalId(),
                tokenUser.getId(),
                approvalStatus.getCode(),
                req.getComments());
        if (!approvalResult.isSuccess())
            throw new BusinessException(SystemError.getDefined(approvalResult.getCode()));
        //如果是审批通过并且审批流畅未结束则直接返回
        if (ApprovalStatus.REVIEW_YES.equals(approvalStatus) && !approvalResult.getData().getIsFinish()) {
            return Result.success();
        }
        //改变订单状态
        AirOrder updateOrder = new AirOrder();
        updateOrder.setId(order.getId());
        updateOrder.setCancelStatus(
                ApprovalStatus.REVIEW_YES.equals(approvalStatus) ?
                        OrderCancelStatus.APPROVAL_SUCCESS.getCode() :
                        OrderCancelStatus.APPROVAL_FAIL.getCode()
        );
        airOrderMapper.updateById(updateOrder);
        //改变订单退款明细状态
        airOrderRefundMapper.update(null,
                Wrappers.<AirOrderRefund>lambdaUpdate().set(AirOrderRefund::getStatus,
                        ApprovalStatus.REVIEW_YES.equals(approvalStatus) ?
                                OrderRefundStatus.AUDIT_SUCCESSFUL.getCode()
                                : OrderRefundStatus.AUDIT_FAILED.getCode())
                        .eq(AirOrderRefund::getOrderId, order.getId()));
        //如果是审批通过则需要通知财务系统
        if (ApprovalStatus.REVIEW_YES.equals(approvalStatus)) {
            refundNotificationFinance(tokenUser, order);
        }
        return Result.success();
    }

    /**
     * 退款审核通过通知财务
     *
     * @param tokenUser
     * @param order
     */
    private void refundNotificationFinance(TokenUser tokenUser, AirOrder order) {
        List<AirOrderRefund> airOrderRefundList = airOrderRefundMapper.selectList(
                Wrappers.<AirOrderRefund>lambdaQuery().eq(AirOrderRefund::getOrderId, order.getId()));
        //获取收款信息
        List<AirOrderCollection> orderCollectionList = airOrderCollectionMapper.selectList(Wrappers.<AirOrderCollection>lambdaQuery()
                .eq(AirOrderCollection::getOrderId, order.getId()));
        //航班信息
        List<AirOrderFlight> orderFlightList = airOrderFlightMapper
                .selectList(Wrappers.<AirOrderFlight>lambdaQuery().eq(AirOrderFlight::getOrderId, order.getId()));
        //旅客信息
        List<BillAddRefundReq> billAddRefundList = Lists.newArrayList();
        //组装财务系统需要数据
        airOrderRefundList.stream().forEach(item -> {
            BillAddRefundReq billAddRefundReq = new BillAddRefundReq();
            billAddRefundReq.setBillNumber(item.getRefundNumber());
            billAddRefundReq.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            billAddRefundReq.setCollectionAmount(item.getRefundAmount());
            billAddRefundReq.setCurrencyId(item.getCurrencyId());
            billAddRefundReq.setCurrencyName(item.getCurrency());
            billAddRefundReq.setExchangeRate(item.getExchangeRate().doubleValue());
            billAddRefundReq.setSaleOrderNumber(order.getOrderNumber());
            billAddRefundReq.setSaleOrderId(order.getId());
            billAddRefundReq.setProductId(orderFlightList.stream().map(AirOrderFlight::getProductId).collect(Collectors.toList()));
            billAddRefundReq.setResourceInfo(orderFlightList.stream()
                    .map(airOrderFlight -> airOrderFlight.getDepCityName() + "-" + airOrderFlight.getArrCityName()).collect(Collectors.toList()));
            billAddRefundReq.setSaleUserId(order.getSalesmanId());
            billAddRefundReq.setSaleUserName(order.getSalesmanName());
            billAddRefundReq.setRefundTypeId(item.getRefundWayId());
            billAddRefundReq.setRefundType(item.getRefundWay());
            billAddRefundReq.setRefundAccountJson(new AccountJson().setCardNumber(item.getRefundAccount()));
            billAddRefundReq.setContactMobile(order.getContactMobile());
            billAddRefundReq.setRefundTime(item.getGmtCreate());

            if (CollectionUtil.isNotEmpty(orderCollectionList)){
                billAddRefundReq.setPayVoucherJson(orderCollectionList.stream()
                        .map(airOrderCollection -> JSON.parseObject(airOrderCollection.getCollectionCertificateJson(), FileJson.class))
                        .collect(Collectors.toList()));
            }

            billAddRefundReq.setRefundRemark(item.getRemark());
            billAddRefundReq.setUserId(tokenUser.getId());
            billAddRefundList.add(billAddRefundReq);
        });
        Result result = iFinanceBillService.addRefund(billAddRefundList);
        if (!result.isSuccess()) {
            throw new BusinessException(SystemError.getDefined(result.getCode()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result refundConfirm(Long id, TokenUser tokenUser) {
        AirOrderRefund airOrderRefund = airOrderRefundMapper.selectById(id);
        Result x = refundConfirm(tokenUser, airOrderRefund, true);
        if (x != null) return x;
        return Result.success(airOrderRefund.getId());
    }

    /**
     * 退款确认
     *
     * @param tokenUser
     * @param airOrderRefund
     * @return
     */
    private Result refundConfirm(TokenUser tokenUser,
                                 AirOrderRefund airOrderRefund, boolean notifyFinance) {
        if (null == airOrderRefund) {
            return Result.failed(SystemError.SYS_411);
        }
        if (airOrderRefund.getStatus().intValue() != OrderRefundStatus.AUDIT_SUCCESSFUL.getCode().intValue()) {
            return Result.failed(SystemError.AIR_ORDER_15008);
        }
        //如果是已经退款的 则不能再次确认
        if (OrderRefundStatus.REFUND_SUCCESSFUL.getCode().equals(airOrderRefund.getStatus())) {
            throw new BusinessException(SystemError.AIR_ORDER_15023);
        }
        //获取订单信息
        AirOrder airOrder = airOrderMapper.selectById(airOrderRefund.getOrderId());
        if (Objects.isNull(airOrder))
            throw new BusinessException(SystemError.AIR_ORDER_15000);
        //修改退款详情
        UpdateWrapper<AirOrderRefund> airOrderRefundUpdateWrapper = new UpdateWrapper<>();
        airOrderRefundUpdateWrapper.lambda().eq(AirOrderRefund::getId, airOrderRefund.getId());
        airOrderRefundUpdateWrapper.lambda().set(AirOrderRefund::getStatus, OrderRefundStatus.REFUND_SUCCESSFUL.getCode());
        airOrderRefundUpdateWrapper.lambda().set(AirOrderRefund::getModifiedId, tokenUser.getId());
        airOrderRefundUpdateWrapper.lambda().set(AirOrderRefund::getGmtModified, LocalDateTime.now());
        airOrderRefundMapper.update(null, airOrderRefundUpdateWrapper);
        //获取该订单下所有退款明细是否已退款
        List<AirOrderRefund> orderRefundList = airOrderRefundMapper.selectList(Wrappers.<AirOrderRefund>lambdaQuery()
                .eq(AirOrderRefund::getOrderId, airOrderRefund.getOrderId())
                .select(AirOrderRefund::getId, AirOrderRefund::getStatus));
        long refundSuccessCount = orderRefundList.stream()
                .filter(item -> OrderRefundStatus.REFUND_SUCCESSFUL.getCode().equals(item.getStatus())).count();
        if (refundSuccessCount == orderRefundList.size()) {
            //修改订单信息
            AirOrder updateOrder = new AirOrder();
            updateOrder.setId(airOrder.getId());
            updateOrder.setCancelStatus(OrderCancelStatus.ALREADY_REFUND.getCode());
            updateOrder.setOrderStatus(OrderStatus.ALREADY_CANCEL.getCode());
            airOrderMapper.updateById(updateOrder);
        }
        if (notifyFinance) {
            //通知财务
            BillOperateRefundReq billOperateRefundReq = new BillOperateRefundReq();
            billOperateRefundReq.setBillNumber(airOrderRefund.getRefundNumber());
            billOperateRefundReq.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            billOperateRefundReq.setUserId(tokenUser.getId());
            Result result = iFinanceBillService.operateRefund(billOperateRefundReq);
            if (!result.isSuccess()) {
                throw new BusinessException(SystemError.getDefined(result.getCode()));
            }
        }
        return Result.success();
    }

    @Override
    public Result refundConfirm(String refundNumber, TokenUser tokenUser) {
        //根据退款单号获取退款详情
        AirOrderRefund airOrderRefund = airOrderRefundMapper.selectOne(Wrappers.<AirOrderRefund>lambdaQuery()
                .eq(AirOrderRefund::getRefundNumber, refundNumber));
        if (airOrderRefund == null)
            throw new BusinessException(SystemError.SYS_411);
        return refundConfirm(tokenUser, airOrderRefund, false);
    }

    @Override
    public Result<PageResponse<AirOrderListDTO>> list(AirOrderListReq req) {
        /**查询订单*/
        Page<AirOrder> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<AirOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotNull(req.getPaymentStatus()), "o.payment_status", req.getPaymentStatus());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getScheduledStatus()), "o.scheduled_status", req.getScheduledStatus());
        queryWrapper.eq(StringUtils.isNotBlank(req.getOrderNumber()), "o.order_number", req.getOrderNumber());
        queryWrapper.gt(ObjectUtils.isNotNull(req.getCreateStar()), "o.gmt_create", req.getCreateStar());
        queryWrapper.lt(ObjectUtils.isNotNull(req.getCreateEnd()), "o.gmt_create", req.getCreateEnd());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getCompanyId()), "f.company_id", req.getCompanyId());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getDepCityId()), "f.dep_city_id", req.getDepCityId());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getArrCityId()), "f.arr_city_id", req.getArrCityId());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getDepAirportId()), "f.dep_airport_id", req.getDepAirportId());
        queryWrapper.eq(ObjectUtils.isNotNull(req.getArrAirportId()), "f.arr_airport_id", req.getArrAirportId());
        Page<AirOrder> iPage = airOrderMapper.queryList(page, queryWrapper);
        List<AirOrder> airOrderList = iPage.getRecords();
        if (CollectionUtil.isEmpty(airOrderList)) {
            return Result.success(new PageResponse<AirOrderListDTO>(new ArrayList<AirOrderListDTO>(), true, true, 0L, 1L, req.getPageSize().longValue()));
        }
        /**查询航班信息*/
        Set<Long> orderIdSet = Sets.newHashSet();
        for (AirOrder airOrder : airOrderList) {
            orderIdSet.add(airOrder.getId());
        }
        QueryWrapper<AirOrderFlight> airOrderFlightQueryWrapper = new QueryWrapper<>();
        airOrderFlightQueryWrapper.lambda().in(AirOrderFlight::getOrderId, orderIdSet);
        List<AirOrderFlight> airOrderFlightList = airOrderFlightMapper.selectList(airOrderFlightQueryWrapper);
        Map<Long, List<AirOrderFlight>> airOrderFlightMap = Maps.newHashMap();
        for (AirOrderFlight airOrderFlight : airOrderFlightList) {
            List<AirOrderFlight> mapValue = airOrderFlightMap.get(airOrderFlight.getOrderId());
            if (null == mapValue) {
                mapValue = Lists.newArrayList();
            }
            mapValue.add(airOrderFlight);
            airOrderFlightMap.put(airOrderFlight.getOrderId(), mapValue);
        }
        List<AirOrderListDTO> airProductListDtoList = EntityUtil.copyList(airOrderList, AirOrderListDTO.class);
        for (AirOrderListDTO airOrderListDTO : airProductListDtoList) {
            List<AirOrderFlight> mapValue = airOrderFlightMap.get(airOrderListDTO.getId());
            List<AirOrderFlightData> airOrderFlightDataList = EntityUtil.copyList(mapValue, AirOrderFlightData.class);
            airOrderListDTO.setAirOrderFlightDataList(airOrderFlightDataList);
            //转换付款状态
            airOrderListDTO.setPaymentStatusName(
                    OrderPaymentStatus.getOrderPaymentStatusName(airOrderListDTO.getPaymentStatus()));
            //转换预订状态
            airOrderListDTO.setScheduledStatusName(
                    OrderScheduledStatus.getOrderScheduledStatusName(airOrderListDTO.getScheduledStatus())
            );
            //来源
            airOrderListDTO.setSourceName(OrderSource.getOrderSourceName(airOrderListDTO.getSource()));
            //判断订单是否为外挂单
            if (null != airOrderListDTO.getOrderType() && airOrderListDTO.getOrderType().intValue() == 1) {
                AirManualOrder airManualOrder = airManualOrderMapper.selectOne(
                        Wrappers.<AirManualOrder>lambdaQuery()
                                .eq(AirManualOrder::getOrderId, airOrderListDTO.getId()));
                //如果是门店出票 需要显示订单确认按钮
                if (airManualOrder != null && airManualOrder.getIssueTicket().equals(1)) {
                    airOrderListDTO.setConfirmBtn(true);
                }
            }
        }
        return Result.success(new PageResponse<AirOrderListDTO>(airProductListDtoList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()),
                iPage.getTotal(), iPage.getCurrent(), iPage.getSize()));
    }

    @Override
    public Result<AirOrderInfoDTO> info(Long id) {
        AirOrder airOrder = airOrderMapper.selectById(id);


        if (airOrder == null)
            throw new BusinessException(SystemError.AIR_ORDER_15000);
        AirOrderInfoDTO airOrderInfoDTO = EntityUtil.copy(airOrder, AirOrderInfoDTO.class);
        //判断订单是否为外挂单
        if (null != airOrder.getOrderType() && airOrder.getOrderType().intValue() == 1) {
            QueryWrapper<AirManualOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(AirManualOrder::getOrderId, id);
            AirManualOrder airManualOrder = airManualOrderMapper.selectOne(queryWrapper);
            if (airManualOrder.getIssueTicket().intValue() == 1) {//如果是门店出票 需要显示订单确认按钮
                airOrderInfoDTO.setConfirmBtn(true);
            }
        }
        //付款狀態
        airOrderInfoDTO.setPaymentStatusName(
                OrderPaymentStatus.getOrderPaymentStatusName(airOrderInfoDTO.getPaymentStatus()));
        //預訂狀態
        airOrderInfoDTO.setScheduledStatusName(
                OrderScheduledStatus.getOrderScheduledStatusName(airOrderInfoDTO.getScheduledStatus()));
        //取消狀態
        airOrderInfoDTO.setCancelStatusName(
                OrderCancelStatus.getOrderCancelStatusName(airOrderInfoDTO.getCancelStatus()));
        //訂單來源
        airOrderInfoDTO.setSourceName(
                OrderSource.getOrderSourceName(airOrderInfoDTO.getSource()));

        /**查询旅客信息*/
        QueryWrapper<AirOrderTourist> airOrderTouristQueryWrapper = new QueryWrapper<>();
        airOrderTouristQueryWrapper.lambda().eq(AirOrderTourist::getOrderId, id);
        List<AirOrderTourist> airOrderTouristList = airOrderTouristMapper.selectList(airOrderTouristQueryWrapper);
        /**查询保险信息*/
        QueryWrapper<AirOrderInsurance> airOrderInsuranceQueryWrapper = new QueryWrapper<>();
        airOrderInsuranceQueryWrapper.lambda().eq(AirOrderInsurance::getOrderId, id);
        List<AirOrderInsurance> airOrderInsuranceList = airOrderInsuranceMapper.selectList(airOrderInsuranceQueryWrapper);
        /**查询航班信息*/
        QueryWrapper<AirOrderFlight> orderFlightQueryWrapper = new QueryWrapper<>();
        orderFlightQueryWrapper.lambda().eq(AirOrderFlight::getOrderId, id);
        List<AirOrderFlight> airOrderFlightList = airOrderFlightMapper.selectList(orderFlightQueryWrapper);
        /**查询收款信息*/
        QueryWrapper<AirOrderCollection> airOrderCollectionQueryWrapper = new QueryWrapper<>();
        airOrderCollectionQueryWrapper.lambda().eq(AirOrderCollection::getOrderId, id);
        List<AirOrderCollection> airOrderCollectionList = airOrderCollectionMapper.selectList(airOrderCollectionQueryWrapper);
        BigDecimal payAmount = new BigDecimal(0);
        for (AirOrderCollection airOrderCollection : airOrderCollectionList) {
            payAmount.add(airOrderCollection.getExchangeRateAfterMoney());
        }
        /**查询退款信息*/
        QueryWrapper<AirOrderRefund> refundQueryWrapper = new QueryWrapper<>();
        refundQueryWrapper.lambda().eq(AirOrderRefund::getOrderId, id);
        List<AirOrderRefund> airOrderRefundList = airOrderRefundMapper.selectList(refundQueryWrapper);
        BigDecimal refundAmount = new BigDecimal(0);
        for (AirOrderRefund airOrderRefund : airOrderRefundList) {
            refundAmount.add(Optional.ofNullable(airOrderRefund.getExchangeRateAfterMoney()).orElse(BigDecimal.ZERO));
        }
        airOrderInfoDTO.setPayAmont(payAmount);
        airOrderInfoDTO.setRefundAmont(payAmount);
        /**开始组装返回结果*/
        List<AirOrderCollectionInfoDTO> airOrderCollectionInfoDTOList = EntityUtil.copyList(airOrderCollectionList, AirOrderCollectionInfoDTO.class);
        List<AirOrderRefundInfoDTO> airOrderRefundInfoDTOList = EntityUtil.copyList(airOrderRefundList, AirOrderRefundInfoDTO.class);
        List<AirOrderTouristInfoDTO> airOrderTouristInfoDTOList = EntityUtil.copyList(airOrderTouristList, AirOrderTouristInfoDTO.class);

        airOrderInfoDTO.setAirOrderCollectionInfoDTOList(airOrderCollectionInfoDTOList);
        airOrderInfoDTO.setAirOrderRefundInfoDTOList(airOrderRefundInfoDTOList);
        /**旅客信息中需要组入价格和保险信息*/
        //旅客保险集合Map
        Map<Long, List<AirOrderInsurance>> touristInsuMap = Maps.newHashMap();
        for (AirOrderInsurance airOrderInsurance : airOrderInsuranceList) {
            String insuredPersons = airOrderInsurance.getInsuredPerson();
            String[] split = insuredPersons.split(",");
            for (String s : split) {
                List<AirOrderInsurance> mapValue = touristInsuMap.get(Long.parseLong(s));
                if (null == mapValue) {
                    mapValue = Lists.newArrayList();
                }
                mapValue.add(airOrderInsurance);
                touristInsuMap.put(Long.parseLong(s), mapValue);
            }
        }
        for (AirOrderTouristInfoDTO airOrderTouristInfoDTO : airOrderTouristInfoDTOList) {
            List<AirOrderInsurance> airOrderInsurances = touristInsuMap.get(airOrderTouristInfoDTO.getId());
            if (null != airOrderInsurances) {
                List<AirOrderInsuranceData> airOrderInsuranceData = EntityUtil.copyList(airOrderInsurances, AirOrderInsuranceData.class);
                airOrderTouristInfoDTO.setAirOrderInsuranceDataList(airOrderInsuranceData);
            }

            List<AirOrderTouristFlightDTO> airOrderTouristFlightDTOList = Lists.newArrayList();
            for (AirOrderFlight airOrderFlight : airOrderFlightList) {
                String flightPrice = airOrderFlight.getFlightPrice();
                List<AirOrderFlightPriceDBData> airOrderFlightPriceDataList = JSON.parseArray(flightPrice, AirOrderFlightPriceDBData.class);
                AirOrderTouristFlightDTO airOrderTouristFlightDTO = EntityUtil.copy(airOrderFlight, AirOrderTouristFlightDTO.class);
                AirProductReservationSettingsDTO airProductReservationSettings =
                        iAirProductReservationSettingsService.getByProductId(airOrderFlight.getProductId()).getData();
                airOrderTouristFlightDTO.setBookingInformation(airProductReservationSettings != null ?
                        airProductReservationSettings.getBookingInformation() : null);
                for (AirOrderFlightPriceDBData airOrderFlightPriceData : airOrderFlightPriceDataList) {
                    if (airOrderFlightPriceData.getTouristTypeId().intValue() == airOrderTouristInfoDTO.getTouristType().intValue()) {
                        airOrderTouristFlightDTO.setPrice(airOrderFlightPriceData.getPrice());
                        airOrderTouristFlightDTO.setServiceChargePrice(airOrderFlightPriceData.getServiceChargePrice());
                        airOrderTouristFlightDTO.setAirProductCostTaxationDataList(airOrderFlightPriceData.getAirProductCostTaxationDTOList());
                        break;
                    }
                }
                airOrderTouristFlightDTOList.add(airOrderTouristFlightDTO);
            }
            airOrderTouristInfoDTO.setAirOrderTouristFlightDTOList(airOrderTouristFlightDTOList);
        }
        airOrderInfoDTO.setAirOrderTouristInfoDTOList(airOrderTouristInfoDTOList);
        return Result.success(airOrderInfoDTO);
    }

    @Override
    public Result updateTouristInfo(AirOrderUpdateTouristData airOrderUpdateTouristData) {
        Long touristId = airOrderUpdateTouristData.getId();
        //如果没有需要更新字段 则直接成功
        if (EntityUtil.allFieldIsNull(airOrderUpdateTouristData.setId(null))) return Result.success();
        //查询旅客信息
        AirOrderTourist airOrderTourist = airOrderTouristMapper.selectById(touristId);
        if (airOrderTourist == null)
            throw new BusinessException(SystemError.AIR_ORDER_15012);
        //获取订单数据
        AirOrder airOrder = airOrderMapper.selectById(airOrderTourist.getOrderId());
        if (airOrder == null)
            throw new BusinessException(SystemError.AIR_ORDER_15000);
        //校验订单状态 只有待付款才能修改旅客信息
        if (!OrderStatus.UN_PAYMENT.getCode().equals(airOrder.getOrderStatus()))
            throw new BusinessException(SystemError.AIR_ORDER_15024);
        //更新数据
        AirOrderTourist copy = EntityUtil.copy(airOrderUpdateTouristData, AirOrderTourist.class);
        copy.setId(touristId);
        int i = airOrderTouristMapper.updateById(copy);
        if (i < 1)
            throw new BusinessException(SystemError.SYS_437);
        return Result.success();
    }


    @Override
    public Result sendMessageToTourist(AirOrderSendMessageToTouristReq sendMessageToTouristReq) {
        InformPassengersWay instance = InformPassengersWay.getInstance(sendMessageToTouristReq.getInformPassengersWay());
        if (Objects.isNull(instance))
            return Result.failed(SystemError.AIR_ORDER_15014);
        switch (instance) {
            //TODO 暂未接入短信
            case SMS:
                HashMap<String, String> paramMap = new HashMap<>();
                paramMap.put("namevotes", "namevotes");
                paramMap.put("use", sendMessageToTouristReq.getMessage());
                paramMap.put("service", "(852)2998 7888");
                try {
                    SmsUtil.sendSms(sendMessageToTouristReq.getAreaCode() +
                            sendMessageToTouristReq.getNumber(), "SMS_215980892", paramMap);
                } catch (Exception e) {
                    log.error("【机票订单收据】发送短信失败,error:{}", e);
                    throw new BusinessException(SystemError.AIREXPRESS_ORDER_60037, e.getMessage());
                }
//                return Result.failed(SystemError.SYS_437);
                return Result.success();
            case EMAIL:
                mailTemplate.sendSimpleMail(sendMessageToTouristReq.getNumber(),
                        "訂單確認通知", sendMessageToTouristReq.getMessage());
                return Result.success();
            default:
                throw new BusinessException(SystemError.AIR_ORDER_15014);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result confirmOrder(AirOrderConfirmOrderReq req) {
        //获取订单
        AirOrder airOrder = airOrderMapper.selectById(req.getOrderId());
        if (Objects.isNull(airOrder))
            return Result.failed(SystemError.AIR_ORDER_15016);
        if (!OrderStatus.CONFIRM_RESERVE.getCode().equals(airOrder.getOrderStatus()))
            return Result.failed(SystemError.AIR_ORDER_15017);
        //把供应商票号更新到航班信息
        req.getSupplierData().stream().forEach(supplierData -> {
            if (Objects.isNull(supplierData.getFlightId()) && Objects.isNull(supplierData.getProductId())) return;
            airOrderFlightMapper.update(
                    new AirOrderFlight()
                            .setSupplierTicketNumber(supplierData.getSupplierTicketNumber())
                            .setSupplierTicketCertificate(supplierData.getCertificate()),
                    Wrappers.<AirOrderFlight>lambdaUpdate()
                            .eq(AirOrderFlight::getOrderId, req.getOrderId())
                            .eq(Objects.nonNull(supplierData.getFlightId()), AirOrderFlight::getId, supplierData.getFlightId())
                            .eq(Objects.nonNull(supplierData.getProductId()), AirOrderFlight::getProductId, supplierData.getProductId())
            );
        });
        //校验该订单下的所有航班是否都已经出票
        List<AirOrderFlight> airOrderFlightList = airOrderFlightMapper.selectList(
                Wrappers.<AirOrderFlight>lambdaQuery()
                        .eq(AirOrderFlight::getOrderId, req.getOrderId())
        );
        //有票号的数量
        long ticketingCount = airOrderFlightList.stream()
                .filter(airOrderFlight -> Objects.nonNull(airOrderFlight.getSupplierTicketNumber())).count();
        //全部已经出票 修改订单状态
        if (ticketingCount == airOrderFlightList.size()) {
            //修改预订状态
            AirOrder updateOrder = new AirOrder();
            updateOrder.setId(airOrder.getId());
            updateOrder
                    .setScheduledStatus(OrderScheduledStatus.RESERVE_SUCCESS.getCode())
                    .setOrderStatus(OrderStatus.RESERVE_SUCCESS.getCode());
            int i = airOrderMapper.updateById(updateOrder);
            if (i < 1)
                throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success();
    }

    @Override
    public Result receivePaymentConfirm(ReceivePaymentConfirmReq req) {
        //校验req数据
        if (Objects.isNull(req.getStatus()) || OrderConfirmationStatus.UNRECOGNIZED.equals(req.getStatus()))
            throw new BusinessException(SystemError.AIR_ORDER_15018);
        //更新认款状态
        int update = airOrderCollectionMapper.update(
                new AirOrderCollection()
                        .setStatus(req.getStatus().getStatus()),
                Wrappers.<AirOrderCollection>lambdaUpdate()
                        .set(StringUtils.isNotBlank(req.getRejectInfo()),
                                AirOrderCollection::getRejectInfo, req.getRejectInfo())
                        .eq(AirOrderCollection::getCollectionNumber, req.getCollectionNumber())
        );
        if (update > 0)
            return Result.success();
        else
            return Result.failed(SystemError.SYS_437);
    }

    @Override
    public Result confirmPayment(List<String> collectionNumberList) {
        if (CollectionUtils.isEmpty(collectionNumberList))
            return Result.success();
        collectionNumberList.stream().forEach(collectionNumber -> {
            receivePaymentConfirm(new ReceivePaymentConfirmReq(collectionNumber, OrderConfirmationStatus.SUBSCRIBED, null));
        });
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result reconfirmThePayment(ReconfirmThePaymentReq req, TokenUser currentUser) {
        //获取支付明细
        AirOrderCollection airOrderCollection = airOrderCollectionMapper.selectOne(
                Wrappers.<AirOrderCollection>lambdaQuery()
                        .eq(AirOrderCollection::getCollectionNumber, req.getCollectionNumber()));
        if (Objects.isNull(airOrderCollection))
            throw new BusinessException(SystemError.AIR_ORDER_15019);
        if (!OrderConfirmationStatus.REJECTED.getStatus().equals(airOrderCollection.getStatus()))
            throw new BusinessException(SystemError.AIR_ORDER_15020);
        // 发送请求再求确认(请求财务系统接口)
        BillOperateRefundReq billOperateRefundReq = new BillOperateRefundReq();
        billOperateRefundReq.setBillNumber(airOrderCollection.getCollectionNumber());
        billOperateRefundReq.setUserId(currentUser.getId());
        billOperateRefundReq.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
        Result result = iFinanceBillService.reConfirm(billOperateRefundReq);
        if (!result.isSuccess()) {
            log.error("再次确认收款失败,财务系统抛出异常:{}", result.getMsg());
            throw new BusinessException(SystemError.SYS_437);
        }
        //修改明细状态
        AirOrderCollection updateCollection = new AirOrderCollection();
        updateCollection.setId(airOrderCollection.getId());
        updateCollection.setStatus(OrderConfirmationStatus.UNRECOGNIZED.getStatus());
        int i = airOrderCollectionMapper.updateById(updateCollection);
        if (i < 1) return Result.failed(SystemError.SYS_437);
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result lockInventory(LockInventoryReq req, TokenUser tokenUser) {
        //获取产品信息
        AirProductInfoDTO product = iAirProductService.info(req.getProductId()).getData();
        if (Objects.isNull(product)) throw new BusinessException(SystemError.AIR_PRODUCT_12004);
        //获取成本信息
        AirProductCostQueryReq airProductCostQueryReq = new AirProductCostQueryReq();
        airProductCostQueryReq.setProductIds(Lists.newArrayList(req.getProductId()));
        airProductCostQueryReq.setStarDate(req.getNeedDate());
        airProductCostQueryReq.setEndDate(req.getNeedDate());
        List<AirProductPriceDTO> cost = iAirProductCostService.queryProductCost(airProductCostQueryReq);
        if (CollectionUtils.isEmpty(cost))
            throw new BusinessException(SystemError.AIR_PRODUCT_12004);
        AirProductPriceDTO productPrice = cost.get(0);

        if (ObjectUtils.isNotEmpty(productPrice.getForbidTheSale()) && productPrice.getForbidTheSale())
        //if (productPrice.isForbidTheSale())
            throw new BusinessException(SystemError.AIR_ORDER_15009);
        if (CollectionUtils.isEmpty(productPrice.getAirProductPriceTouristDTOList()))
            throw new BusinessException(SystemError.AIR_PRODUCT_12021);
        //获取旅客类型
        Map<Integer, List<AirProductPriceDateDTO>> collect = productPrice.getAirProductPriceTouristDTOList()
                .stream()
                .collect(Collectors.toMap(AirProductPriceTouristDTO::getAirTouristTypeId,
                        AirProductPriceTouristDTO::getAirProductPriceDateDTOList));
        req.getAirTouristTypeIds().stream().forEach(touristTypeId -> {
            if (!collect.containsKey(touristTypeId)) throw new BusinessException(SystemError.AIR_ORDER_15021);
            //校验库存是否足够
            List<AirProductPriceDateDTO> airProductPriceDateDTOS = collect.get(touristTypeId);
            if (CollectionUtils.isEmpty(airProductPriceDateDTOS)) throw new BusinessException(SystemError.AIR_ORDER_15009);
            //根据日期分组 可根据日期get到当日剩余库存
            Map<LocalDate, Integer> dailyInventory = airProductPriceDateDTOS.stream()
                    .collect(Collectors.toMap(AirProductPriceDateDTO::getDate, AirProductPriceDateDTO::getDailyStock));
            Integer stock = dailyInventory.get(req.getNeedDate());
            if (req.getPurchaseQuantity().compareTo(stock) == 1)
                throw new BusinessException(SystemError.AIR_ORDER_15009);
        });
        //库存够的时候需要新增售卖记录
        salesRecord(req.getPurchaseQuantity(), tokenUser, req.getOrderId(), product.getId(), req.getNeedDate());
        return Result.success();
    }

    @Override
    public Result releaseInventory(Long productId, Long orderId) {
        boolean remove = iAirProductSaleRecordService.removeByProductAndOrderId(productId, orderId);
        if (remove) throw new BusinessException(SystemError.AIR_ORDER_15022);
        return Result.success();
    }

    @Override
    public Result<List<OrderRefundDTO>> getOrderRefundList(String refundNumber) {
        AirOrderRefund airOrderRefund = airOrderRefundMapper.selectOne(Wrappers.<AirOrderRefund>lambdaQuery()
                .eq(AirOrderRefund::getRefundNumber, refundNumber));
        if (Objects.isNull(airOrderRefund)) {
            throw new BusinessException(SystemError.AIR_ORDER_15016);
        }
        List<AirOrderRefund> list = airOrderRefundMapper.selectList(
                Wrappers.<AirOrderRefund>lambdaQuery()
                        .eq(AirOrderRefund::getOrderId, airOrderRefund.getOrderId()));
        if (CollectionUtils.isEmpty(list))
            return Result.success(Lists.newArrayList());
        //获取订单信息
        AirOrder airOrder = airOrderMapper.selectById(airOrderRefund.getOrderId());
        if (Objects.isNull(airOrder)) {
            throw new BusinessException(SystemError.AIR_ORDER_15016);
        }
        //实收金额
        BigDecimal actualAmount = airOrderCollectionMapper.selectList(Wrappers.
                <AirOrderCollection>lambdaQuery()
                .eq(AirOrderCollection::getOrderId, airOrder.getId()))
                .stream().map(AirOrderCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //封装参数
        List<OrderRefundDTO> orderRefundDTOS = list.stream().map(item -> {
            OrderRefundDTO orderRefundDTO = new OrderRefundDTO();
            orderRefundDTO.setId(item.getId());
            orderRefundDTO.setRefundId(item.getId());
            orderRefundDTO.setBusinessType(SystemBusinessType.AIR_TICKET.getCode());
            orderRefundDTO.setRefundNumber(item.getRefundNumber());
            orderRefundDTO.setRefundAccount(item.getRefundAccount());
            orderRefundDTO.setTotalReceivables(airOrder.getOrderAmount());
            orderRefundDTO.setPaidInAmount(actualAmount);
            orderRefundDTO.setRefundAmount(item.getRefundAmount());
            orderRefundDTO.setCurrency(item.getCurrency());
            orderRefundDTO.setRefundType(item.getRefundWay());
            orderRefundDTO.setRefundReason(item.getRefundReason());
            orderRefundDTO.setRemark(item.getRemark());
            return orderRefundDTO;
        }).collect(Collectors.toList());
        return Result.success(orderRefundDTOS);
    }

    @Override
    public Result supplierConfirmOrder(SupplierConfirmOrderReq req, Long userId) {
        AirOrder airOrder = baseMapper.selectOne(Wrappers.<AirOrder>lambdaQuery().eq(AirOrder::getOrderNumber, req.getSaleNumber()));
        com.ctshk.common.utils.Assert.nonNull(airOrder, SystemError.AIR_ORDER_15016);
        OrderScheduledStatus status = OrderScheduledStatus.getByCode(req.getReserveStatus());
        com.ctshk.common.utils.Assert.nonNull(status, SystemError.AIR_ORDER_15029);
        //修改预订状态
        AirOrder updateOrder = new AirOrder();
        updateOrder.setId(airOrder.getId());
        updateOrder
                .setScheduledStatus(status.getCode())
                .setOrderStatus(OrderScheduledStatus.RESERVE_SUCCESS.equals(status) ?
                        OrderStatus.RESERVE_SUCCESS.getCode() : OrderStatus.RESERVE_FAIL.getCode());
        int i = airOrderMapper.updateById(updateOrder);
        return i > 0 ? Result.success() : Result.failed(SystemError.SYS_437);
    }

    @Override
    public Result<List<AirOrderListDTO>> recentToNow(LocalDateTime recent, LocalDateTime now) {
        List<AirOrder> orderList = baseMapper.selectList(Wrappers.<AirOrder>lambdaQuery()
                .eq(AirOrder::getIsDeleted,IsDeletedCode.NO.getCode())
                .ge(recent != null,AirOrder::getGmtModified, recent)
                .le(AirOrder::getGmtModified, now));
        List<AirOrderListDTO> airOrderListDTOS = EntityUtil.copyList(orderList, AirOrderListDTO.class);

        for (AirOrderListDTO airOrderListDTO : airOrderListDTOS) {
            List<AirOrderFlight> airOrderFlights = airOrderFlightMapper.selectList(Wrappers.<AirOrderFlight>lambdaQuery()
                    .eq(AirOrderFlight::getOrderId,airOrderListDTO.getId()));
            airOrderListDTO.setAirOrderFlightDataList(EntityUtil.copyList(airOrderFlights, AirOrderFlightData.class));
        }

        return Result.success(airOrderListDTOS);
    }

    @Override
    public CallPayDTO getCallPayInfo(Long orderId) {
        AirOrder airOrder = airOrderMapper.selectOne(Wrappers.<AirOrder>lambdaQuery()
                .eq(AirOrder::getId, orderId)
                .eq(AirOrder::getPaymentStatus, OrderPaymentStatus.UN_PAYMENT.getCode())
                .eq(AirOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .select(AirOrder::getId, AirOrder::getOrderNumber, AirOrder::getReceivableAmount,
                        AirOrder::getPayExpireDate, AirOrder::getSalesmanId, AirOrder::getPaymentStatus));
        if (airOrder == null) {
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60002);
        }
        CallPayDTO callPayDTO = EntityUtil.copy(airOrder, CallPayDTO.class);
        callPayDTO.setOrderValidTime(airOrder.getPayExpireDate());
        callPayDTO.setTotalFee(airOrder.getReceivableAmount());
        callPayDTO.setCurrency(PayCurrency.HKD);
        callPayDTO.setSubject("机票订单支付");
        callPayDTO.setBody("机票订单支付");
        return callPayDTO;
    }

    @Override
    public List<AirOrderDTO> queryOrderDTOList(LocalDateTime start, LocalDateTime end) {
        return EntityUtil.copyList(baseMapper.selectList(Wrappers.<AirOrder>lambdaQuery()
                .eq(AirOrder::getIsDeleted, IsDeletedCode.NO.getCode())
                .ge(AirOrder::getGmtCreate, start)
                .le(AirOrder::getGmtCreate, end)),AirOrderDTO.class);
    }


    /**
     * 根据币种ID获取汇率，获取汇率,
     *
     * @return
     */
    private MainDataCurrencyQueryDTO getExchangeRateByCurrencyId(Long currencyId) {
        MainDataCurrencyUpdateStatusReq mainDataCurrencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
        mainDataCurrencyUpdateStatusReq.setId(currencyId);
        Result<MainDataCurrencyQueryDTO> queryCurrencyRateResult = mainDataCurrencyService.query(mainDataCurrencyUpdateStatusReq);
        if (!queryCurrencyRateResult.isSuccess()) {
            SystemError defined = SystemError.getDefined(queryCurrencyRateResult.getCode());
            throw new BusinessException(defined);
        }
        return queryCurrencyRateResult.getData();
    }

}
